2012-11-10 32 views
2

我需要C#字符串的數組傳遞到C代碼元帥使用對一個字符串數組從C#爲C代碼/調用

例C代碼

void print_string_array(const char** str_array, int length){ 
    for (int i = 0; i < length; ++i) { 
     printf("Sting[%l] = %s\n", i, str_array[i]); 
    } 
} 
,我曾嘗試

C#(這沒有工作)

string foo[] = {"testing", "one", "two", "three"}; 
print_string_array(foo, foo.Length); 

[DllImport(my_C_dll, CharSet = CharSet.Ansi)] 
private static extern void print_string_array([In][MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] sa, int length); 

與System.AccessViolationException System.AccessViolationException失敗:試圖讀取或寫入保護內存。這通常表明其他內存已損壞。

我也曾嘗試(這還沒有工作)

string[] foo = {"testing", "one", "two", "three"}; 
IntPtr[] s_array = new IntPtr[foo.Length]; 

for(int i = 0; i < foo.Length; ++i) 
{ 
    s_array[i] = Marshal.StringToCoTaskMemAnsi(foo[i]) 
} 
print_string_array(s_array, s_array.Length); 

[DllImport(my_C_dll, CharSet = CharSet.Ansi)] 
private static extern void print_string_array(IntPtr[] sa, int length); 

這也失敗,出現System.AccessViolationException System.AccessViolationException:嘗試讀取或寫入受保護的內存。這通常表明其他內存已損壞。

任何人都知道如何將字符串數組從C#傳遞給C?

編輯: 添加了來自David Heffernam的每條建議的錯誤消息。 在C代碼中將size_t更改爲int,因爲它不影響我正在嘗試執行的操作。 仍然收到相同的錯誤。

回答

4

您可以簡單地聲明你的函數在C#這樣的:

[DllImport(my_C_dll, CallingConvention=CallingConvention.Cdecl)] 
static extern void print_string_array([In] string[] str_array, IntPtr length); 

經上所記,你的C++代碼似乎使用cdecl調用約定。所以你可能需要進行C#聲明匹配。我懷疑這是你面臨的主要問題。

另請注意,用於參數length的參數在32位進程中爲32位寬,在64位進程中爲64位。所以正確的C#類型是IntPtr。我個人會在C++和C#代碼中聲明它是int


最後一句忠告。當您遇到問題時,請在您的問題中包含錯誤消息。我懷疑你的第一個代碼失敗,此錯誤:

A call to PInvoke function 'MyApp!MyApp.Program::print_string_array' has unbalanced the stack.

如果你已經包含在這個問題它會是一個很大的幫助。

+0

我的原始代碼仍然失敗;然而,我開始了一個乾淨的測試項目,代碼首次嘗試使用這種方法。謝謝。 – gnash117

2

你的第二次嘗試是非常接近。請嘗試以下操作:

string[] foo = {"testing", "one", "two", "three"}; 
IntPtr[] s_array = new IntPtr[foo.Length]; 

for(int i = 0; i < foo.Length; ++i) 
{ 
    s_array[i] = Marshal.StringToHGlobalAnsi(foo[i]) 
} 
GCHandle gH = GCHandle.Alloc(s_array, GCHandleType.Pinned); 
print_string_array(gH.AddrOfPinnedObject(), s_array.Length); 
gH.Free(); 
for(int i = 0; i < foo.Length; ++i) 
{ 
    Marshal.FreeHGlobal(s_array[i]) 
} 

[DllImport(my_C_dll, CharSet = CharSet.Ansi)] 
private static extern int print_string_array(IntPtr sa, int length); 
+1

這實際上與問題中的代碼相同。編組已經由編組固定。 –

0

爲什麼「print_string_array(IntPtr sa,int length);」 而不是「print_string_array(IntPtr [] sa,int length);」 ? print_string_array在C端看什麼? print_string_array(char ** sa,int length); print_string_array(char ** sa,int length); ?