2013-08-28 21 views
3
  • 我無法完全訪問DLL源,只有標題。
  • 在我的實際代碼的參數的名稱是更具描述性的

嗨,我試圖讓一個非託管的DLL,它接受所有字符通話*變量,其中兩個作爲「返回」值。 in1-8是輸入,in9和10是長度爲512的char *,並且是空的。通話完成後,應該填寫結果數據。如何傳遞和接收來自C#的char *到非託管C++ DLL的數據

下面是我試圖一起工作的樣本定義:

[DllImport("mydll.dll")] 
public static extern IntPtr foo(
    IntPtr in1, 
    IntPtr in2, 
    IntPtr in3, 
    IntPtr in4, 
    IntPtr in5, 
    IntPtr in6, 
    IntPtr in7, 
    IntPtr in8, 
    ref IntPtr result1, 
    ref IntPtr result2); 

這裏是我的電話:

IntPtr param1 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param2 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param3 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param4 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param5 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param6 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param7 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param8 = Marshal.StringToHGlobalUni("testdata"); 
IntPtr param9 = IntPtr.Zero; 
IntPtr param10 = IntPtr.Zero; 

foo(param1, param2, param3, param4, param5, param6, param7, param8, ref param9, ref param10); 

要打印一個IntPtr,我這樣做:

string str = Marshal.PtrToStringUni(param9); 
Console.WriteLine(str); 

在給我的「示例」中,C++調用如下所示:

char result1[512]=""; 
char result2[512]=""; 
foo("testdata", "testdata", "testdata", "testdata", "testdata", "testdata", "testdata", "testdata", result1, result2); 
printf("%s,%s\n",result1,result2); 

問題:在我試過的每種方法中,包括char [512]轉換爲byte [],StringBuilder大小512,IntPtr等等。param9和param10值在每個返回時都是空的。任何人都可以幫我解決這個問題嗎?提前致謝。

編輯 經過下面的一些有用的評論和更多的谷歌搜索後,我修補了我亂碼的工作。這裏的編輯:

[DllImport("mydll.dll")] 
public static extern IntPtr foo(
    IntPtr in1, 
    IntPtr in2, 
    IntPtr in3, 
    IntPtr in4, 
    IntPtr in5, 
    IntPtr in6, 
    IntPtr in7, 
    IntPtr in8, 
    IntPtr result1, 
    IntPtr result2); 

我擺脫了兩個結果字符數組的ref。

IntPtr param1 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param2 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param3 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param4 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param5 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param6 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param7 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param8 = Marshal.StringToHGlobalAnsi("testdata"); 
IntPtr param9 = Marshal.AllocHGlobal(512 * sizeof(int)); 
IntPtr param10 = Marshal.AllocHGlobal(512 * sizeof(int)); 

foo(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10); 

上面我分配param9和10,而不是IntPtr.Zero

//printing.. 
string str = Marshal.PtrToStringAnsi(param9); 

而且使用字符串,由於下面的答案一個更簡單的方法:

[DllImport("mydll.dll")] 
public static extern IntPtr foo(
    string in1, 
    string in2, 
    string in3, 
    string in4, 
    string in5, 
    string in6, 
    string in7, 
    string in8, 
    StringBuilder result1, 
    StringBuilder result2); 

則:

StringBuilder resultA = new StringBuilder(512); 
StringBuilder resultB = new StringBuilder(512); 

foo("test", "test", "test", "test", "test", "test", "test", "test", resultA, resultB); 

印刷:

Console.WriteLine(resultA.ToString()); 

現在看起來好多了,實際上現在的工作,謝謝你們!很容易混淆打開50個谷歌搜索標籤。

+2

可能的重複http://stackoverflow.com/questions/803488/marshalling-c-dll-code-into-c-sharp – slfan

+1

您是否嘗試過沒有ref參數的StringBuilder?我認爲這應該工作。 – slfan

+0

@slfan,我已經嘗試過沒有在StringBuilder上的參考,它仍然是空的。感謝您的建議! – ayjis

回答

6

假設你有下面的C聲明

extern "C" __declspec(dllexport) { 
    void foo(char * input, char * output); 
} 

我會定義下面的C#定義:

[DllImport("mydll.dll", EntryPoint="foo")] 
public static extern void Foo(string input, StringBuilder output); 

,呼叫會是這樣:

string input = "input"; 
var output = new StringBuilder(512); 
Foo(input, output); 

如果可能的話儘量避免不安全的代碼。

相關問題