从c+;返回指针数组+;到c# 下面我有一个C++代码片段。 我需要返回指针数组(到TempStruct)
问题是在c端我只得到一个元素。另一方面,我得到AV从c+;返回指针数组+;到c# 下面我有一个C++代码片段。 我需要返回指针数组(到TempStruct),c#,c++,pinvoke,C#,C++,Pinvoke,问题是在c端我只得到一个元素。另一方面,我得到AV **C++** extern "C" __declspec(dllexport) void GetResult(TempStruct** outPtr, long *size) { *outPtr = (TempStruct*)new TempStruct*[2]; outPtr[0] = new TempStruct("sdf", 123); outPtr[1] = new TempStruct("
**C++**
extern "C" __declspec(dllexport) void GetResult(TempStruct** outPtr, long *size)
{
*outPtr = (TempStruct*)new TempStruct*[2];
outPtr[0] = new TempStruct("sdf", 123);
outPtr[1] = new TempStruct("abc", 456);
*size = 2;
}
**C#**
[DllImport("test.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetResult(out IntPtr outPtr, out int size);
IntPtr ptr = IntPtr.Zero;
int length;
GetResult(out ptr, out length);
int size = Marshal.SizeOf(typeof(TempStruct));
TempStruct[] someData2 = new TempStruct[length];
for (int i = 0; i < length; i++)
{
IntPtr wskptr = (IntPtr)(ptr.ToInt64() + (size * i));
someData2[i] = (TempStruct)Marshal.PtrToStructure(wskptr, typeof(TempStruct));
}
**C++**
外部“C”uu declspec(dllexport)void GetResult(TempStruct**outPtr,long*size)
{
*outPtr=(TempStruct*)新的TempStruct*[2];
outPtr[0]=新的临时结构(“sdf”,123);
outPtr[1]=新的临时结构(“abc”,456);
*尺寸=2;
}
**C#**
[DllImport(“test.dll”,CallingConvention=CallingConvention.Cdecl,CharSet=CharSet.Ansi)]
公共静态外部void GetResult(out IntPtr outPtr,out int size);
IntPtr ptr=IntPtr.0;
整数长度;
GetResult(输出ptr、输出长度);
int size=Marshal.SizeOf(typeof(TempStruct));
TempStruct[]someData2=新的TempStruct[length];
for(int i=0;i
你做错了
您正在混合指针类型
通过使用new TempStruct()
可以创建指向TempStruct
的指针数组。我给出的示例创建了一个TempStruct
数组。看到区别了吗
现在TempStruct**outPtr
应该是TempStruct***outPtr
(因为您希望返回(*
)指针数组(*
)……或者TempStruct**
,如果您愿意的话:-)
换行
someData2[i] = (TempStruct)Marshal.PtrToStructure(Marshal.ReadIntPtr(wskptr), typeof(TempStruct));
因为你必须读单指针
我希望您使用delete删除各种TempStruct
,并使用
delete[] ptr;
运算符删除结构数组
完整示例:
C++:
它更正确,因为
outPtr
和size
都不能为NULL
。看见C签名是相同的。 < P> C++代码是错误的。它将返回指向struct的指针数组。您对new
返回的值进行强制转换的事实应该提醒您犯了错误。您希望返回一个struct数组
应该是:
*outPtr = new TempStruct[2];
(*outPtr)[0].str = "sdf";
(*outPtr)[0].i = 123;
(*outPtr)[1].str = "abc";
(*outPtr)[1].i = 456;
*size = 2;
你的意思是不是例如
(*outPtr)[0]
?既然您分配了一个指针数组,那么outPtr
参数不应该是一个三重指针(即TempStruct***outPtr
)吗?分配内存时所做的强制转换是为了掩盖最后一个错误,千万不要强制转换new
的结果。你的意思是不是例如(*outPtr)[0]
?:)@约阿希姆皮勒堡是的。非常感谢。我只是垃圾在C++!DavidHeffernan唯一的问题是,您不能轻松地使用具有该语法的参数化构造函数。有人问过这个问题,以及解决方案。可以使用,但我更愿意去看牙医…:-)@xanatos是的,但我更喜欢它,而不是那些额外的分配和间接的方式。如果调用方知道需要多少元素,那么整个过程就可以由p/invoke封送器完成,而无需显式分配。在C++代码中,我只需生成一个返回新值的函数:<代码> TempStruct MakeNewStruct(const char * STR,const int i)< /> >,我仍然只能读取第一个项。我将参数更改为三个指针,并按照您上面所写的那样更改了c代码delete[]ptr
是不够的。问题中的代码也要求删除每个项目。这就是为什么我认为C++代码是错误的。@ DavidHeffernan…更正。@John请参阅完整示例。@John示例中的outPtr
通常不是NULL
。如果你从C++中使用了这个方法,你会:<代码> TimStutt**PTR;整数大小;GetResult(&ptr,&size),因此您将为outPtr
传递一个值:&ptr
。在C#中也一样,使用out ptr
。显然,您可以添加一个NULL
检查,因为有人可以执行GetResult(NULL,NULL)
。从技术上讲,C++中“正确”的方式是<代码>无效的GETREST(TestSufft *&OutpTR,int和size)< /C>,因为两者都是<代码> OutpTr> /Cuff>和<代码> size <代码>不能是代码> null < /C> >(参见)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1), Serializable]
internal struct TempStruct
{
public string str;
public int num;
}
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
static extern void GetResult(out IntPtr outPtr, out int numPtr);
[DllImport("NativeLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
static extern void FreeSomeData(IntPtr ptr, int num);
// C++ will return its TempStruct array in ptr
IntPtr ptr;
int size;
GetResult(out ptr, out size);
TempStruct[] someData2 = new TempStruct[size];
for (int i = 0; i < size; i++)
{
IntPtr ptr2 = Marshal.ReadIntPtr(ptr, i * IntPtr.Size);
someData2[i] = (TempStruct)Marshal.PtrToStructure(ptr2, typeof(TempStruct));
}
// Important! We free the TempStruct allocated by C++. We let the
// C++ do it, because it knows how to do it.
FreeSomeData(ptr, size);
__declspec(dllexport) void GetResult(TempStruct **&outPtr, int &size)
{
outPtr = new TempStruct*[2];
outPtr[0] = new TempStruct("sdf", 123);
outPtr[1] = new TempStruct("abc", 456);
size = 2;
}
*outPtr = new TempStruct[2];
(*outPtr)[0].str = "sdf";
(*outPtr)[0].i = 123;
(*outPtr)[1].str = "abc";
(*outPtr)[1].i = 456;
*size = 2;