接收 pinvoke 结构的垃圾值

receiving garbage values for pinvoke structure

我正在尝试通过 PINVOKE 将结构从 c# 发送到 c++ dll

这是我的代码

C++ 函数

struct sampleStruct
{
int* intP;
char** charP;
};

TESTDLL_API int testStructCall(int *iPtr,char **cPtr,sampleStruct* st)
{ return 42;}

C# 调用

[StructLayout(LayoutKind.Sequential)]
struct sampleStruct
{
   public int[] intArr; 
   public string[] strArr;}

[DllImport("testDll.dll", CallingConvention = CallingConvention.Cdecl,   CharSet = CharSet.Ansi)]
    static private extern int testStructCall( int[] intArr, string[] strArr, ref sampleStruct st);


        string[] strArr = { "string 1", "string 2" };
        int[] intArr = { 10, 20, 30, 40 };

        sampleStruct struc = new sampleStruct();
        struc.intArr = intArr;
        struc.strArr = strArr;
        testStructCall( intArr,  strArr, ref struc);

在 C++ 中,我可以正确接收前两个参数,但结构成员显示垃圾值。我在这里错过了什么?

结构中的数组不能编组为 UnmanagedType.LPArray,这是这些成员访问非托管代码所需要的。

您可能知道,当数组作为函数的参数出现时,它们会被正确编组。如果必须在结构内传递这些数组,则需要在 C# 结构声明中将成员声明为 IntPtr,并手动编写编组代码。这对于整数数组来说不是很难,只是固定数组的情况。对于字符串数组,还有更多的工作。您需要一个 IntPtr 的数组,然后用对 Marshal.StringToCoTaskMemAnsi.

的调用填充该数组

看起来像这样:

var intHandle = GCHandle.Alloc(intArr, GCHandleType.Pinned);
struc.intArr = intHandle.AddrOfPinnedObject();

var strPtrArr = new IntPtr[strArr.Length];
for (int i = 0; i < strPtrArr.Length; i++)
    strPtrArr[i] = Marshal.StringToCoTaskMemAnsi(strArr[i]);
var strHandle = GCHandle.Alloc(strPtrArr, GCHandleType.Pinned);
struc.strArr = strHandle.AddrOfPinnedObject();

testStructCall(intArr, strArr, ref struc);

intHandle.Free();
strHandle.Free();
for (int i = 0; i < strPtrArr.Length; i++)
    Marshal.FreeCoTaskMem(strPtrArr[i]);