c++ - 使用 p/invoke 将字符串数组从 C# 编码到 C 代码

标签 c++ .net interop pinvoke marshalling

我需要将 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:试图读取或写入 protected 内存。这通常表明其他内存已损坏。

我也试过了(这个也没用)

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 : Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

有人知道如何将字符串数组从 C# 传递到 C 吗?


更新: 根据 David Heffernan 的建议添加了错误消息。 在 C 代码中将 size_t 更改为 int,因为它不会影响我尝试做的事情。 仍然得到相同的错误。

最佳答案

您可以像这样在 C# 中简单地声明您的函数:

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

如所写,您的 C++ 代码似乎使用 cdecl 调用约定。因此,您可能需要使 C# 声明匹配。我怀疑这是您面临的主要问题。

另请注意,用于 length 参数的 size_t 在 32 位进程中为 32 位宽,在 64 位进程中为 64 位宽。所以正确的 C# 类型是 IntPtr。我个人会在 C++ 和 C# 代码中将其声明为 int


最后的忠告。当您遇到失败时,请在您的问题中包含错误消息。我怀疑您的第一个代码因此错误而失败:

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

如果您在问题中包含了这一点,那将是一个很大的帮助。

关于c++ - 使用 p/invoke 将字符串数组从 C# 编码到 C 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13317931/

相关文章:

C++ : Ask user input without pressing enter using assembly?

c++ - 找出堆内存损坏的地方

c# - 从列表中过滤重复项

c# - 使用 C# Excel Interop 在 Excel 中计算用户定义的函数

c# - 从 C# 编码结构数组

c++ - 如何将对象从 D 传递到 C++?

c++ - 如何通过引用或值或指针在 C++ 中传递数组?

c++ - Arduino 上数学运算的计时速度 - 异常

c# - 在 C# 中重复一个字符的最佳方法

C# - AsyncCallback 中的异常传播问题