接收 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]);
我正在尝试通过 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]);