2013-10-09 76 views
1

我無法得到下面的p/invoke代碼工作,請幫助,謝謝。pinvoke - 傳遞一個字符串[]作爲參數

下面的頂點在C++調用後保持爲空。我試過使用IntPtr而不是string [],IntPtr在C++調用後保持爲0。

C++代碼

extern "C" __declspec(dllexport) 
float compute_similarity(char** vertices) 
{  
    vertices = new char*[2]; 
    vertices[0] = new char[3]; 
    vertices[1] = new char[3]; 

    strcpy(vertices[0], "he"); 
    strcpy(vertices[1], "ha"); 

    return 1.01; 
} 

C#代碼

[DllImport("demo.dll", EntryPoint = "compute_similarity", 
    CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)] 
static extern float compute_similarity(out string[] vertices); 
//also tried 'static extern float compute_similarity(out IntPtr vertices);' 

public string Func() 
{ 
    string[] vertices; //also tried 'IntPtr vertices' 
    float sim = compute_similarity(out vertices); 
    //break point here vertices stays null(or 0 for IntPtr) 
    return sim.ToString(); 
} 
+0

無法看到您的C++代碼的問題。我複製/粘貼它,並替換傳遞參數與本地字符**,它爲我工作得很好。你如何調用函數compute_similarity()? (你傳遞給它的是什麼?) –

+1

這段代碼不能可靠地從C++調用,當你從C#調用它時,它不會變得更好。調用者*有*調用delete []來獲取釋放數組的內存。這有時可以從C++起作用,你需要相當的運氣並仔細控制DLL和客戶端代碼所使用的編譯器版本。它保證不能從C#工作,它不知道如何調用C++ delete []運算符。你得到0是因爲你的C++代碼不好,vertices參數應該是char ***。 –

+0

首先讓你的函數適用於C++客戶端。它看起來像你需要char *** - 偉大的設計! –

回答

2

我不認爲它能夠正確做到這樣,因爲你沒有指定的P/Invoke必須釋放內存的方式在將其轉換爲託管字符串後調用delete[]

但是,的BSTRMarshalAs屬性,您可能有戰鬥機會。

extern "C" __declspec(dllexport) 
float compute_similarity(SAFEARRAY** vertices) 
{ 
    SAFEARRAY *pArr = SafeArrayCreateVector(VT_BSTR, 0, 2); 
    if(pArr != NULL) 
    { 
     LONG index = 0; 
     BSTR bs = SysAllocString(L"he"); 
     SafeArrayPutElement(pArr, &index, bs); 
     SysFreeString(bs); 
     index = 1; 
     bs = SysAllocString(L"ha"); 
     SafeArrayPutElement(pArr, &index, bs); 
     SysFreeString(bs); 
    } 
    *vertices = pArr; 
    return 1.01; 
} 
[DllImport("demo.dll", EntryPoint = "compute_similarity", CallingConvention = CallingConvention.Cdecl)] 
static extern float compute_similarity(
    [Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType=VarEnum.VT_BSTR)] out string[] vertices 
); 

你仍然可以使用IntPtr(和做手工的C#側封送處理,而導出delete_strings功能),但請記住,你的函數必須接受它的char**通過引用,或者它實際上不能修改它。

相關問題