将指向结构数组指针的指针从 C# 传递到 C++
Passing pointer to pointer of array of structure from C# to C++
我想将指向结构数组指针的指针从 C# 传递到 C++。使用以下代码,我只获取 C++ 中的第一个元素,不传递数组的第二个和第三个元素。为什么?此外,尝试使用 StructureToPtr 但没有帮助。我做错了什么?
C++代码
struct structure
{
short ps;
};
__declspec(dllexport)short Testmethod(structure** aa)
{
if (aa!= 0 && aa[0]->ps == 26 && aa[1]->ps == 27)
{
return 1;
}
return 0;
}
C#代码
[DllImport("Wrapper.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern short Testmethod(ref IntPtr a);
[StructLayout(LayoutKind.Sequential)]
public struct SampleStructure
{
public short ps;
};
SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr ptr = gch.AddrOfPinnedObject();
ret = Testmethod(ref ptr);
我无法更改 C++ 代码,我无权访问它。如果将 c++ 代码更改为以下任一方式,它就可以工作。如何在不更改 C++ 代码的情况下实现它?
更新:
方法 1: 如果我更改 c++ 代码,则可以工作。但我无法更改 C++ 代码。这不是我的代码。
C++代码
__declspec(dllexport)short Testmethod(structure* aa)
C#代码
fixed (SampleStructure* pArray = dataInformation)
{
ret = Testmethod(pArray);
}
方法 2: 如果我更改 c++ 代码,则可以工作。但我无法更改 C++ 代码。这不是我的代码。
C++代码
__declspec(dllexport)short Testmethod(structure Getcsharpval[], int size)
c#代码
public unsafe static extern short Testmethod([MarshalAs(UnmanagedType.LPArray,SizeParamIndex=3)] SampleStructure[] array);
SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
ret = Testmethod( data);
我认为你的 c 函数有错误的原型。
尝试:
_declspec(dllexport)short Testmethod(structure* aa)
{
if (aa != 0
&& aa[0].ps == 26 && aa[1].ps == 27)
{
return 1;
}
return 0;
}
在您的 C# 示例中,您有一个结构数组。该数组是引用类型,您更正需要固定内存。该数组是值类型(并且不需要引脚)的结构内存中的序列。所以在数组中你没有指针,而是直接的结构。
您需要将 IntPtr[]
传递给 C++ 代码。
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern short Testmethod(IntPtr[] aa)
分配一个 IntPtr[]
数组并填充它。通过固定每个结构并使用固定对象的地址来执行此操作。或者使用 Marshal.StructureToPtr
。如果使用后者,则必须在调用后释放非托管内存。
好的,我通过使用以下代码创建指向结构指针的指针来解决。
[DllImport("Wrapper.dll", CallingConvention = CallingConvention.StdCall)]
public unsafe static extern short Testmethod (SampleStructure** passstructurepointer);
unsafe
{
fixed(SampleStructure** p2p = new SampleStructure*[3])
{
for (short i = 0; i < 3; i++)
{
var a = stackalloc SampleStructure[1];
a->ps = i;
p2p[i] = a;
}
var s= Testmethod(p2p);
}
}
我想将指向结构数组指针的指针从 C# 传递到 C++。使用以下代码,我只获取 C++ 中的第一个元素,不传递数组的第二个和第三个元素。为什么?此外,尝试使用 StructureToPtr 但没有帮助。我做错了什么?
C++代码
struct structure
{
short ps;
};
__declspec(dllexport)short Testmethod(structure** aa)
{
if (aa!= 0 && aa[0]->ps == 26 && aa[1]->ps == 27)
{
return 1;
}
return 0;
}
C#代码
[DllImport("Wrapper.dll", CallingConvention = CallingConvention.Cdecl)]
public unsafe static extern short Testmethod(ref IntPtr a);
[StructLayout(LayoutKind.Sequential)]
public struct SampleStructure
{
public short ps;
};
SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
GCHandle gch = GCHandle.Alloc(data, GCHandleType.Pinned);
IntPtr ptr = gch.AddrOfPinnedObject();
ret = Testmethod(ref ptr);
我无法更改 C++ 代码,我无权访问它。如果将 c++ 代码更改为以下任一方式,它就可以工作。如何在不更改 C++ 代码的情况下实现它? 更新:
方法 1: 如果我更改 c++ 代码,则可以工作。但我无法更改 C++ 代码。这不是我的代码。
C++代码
__declspec(dllexport)short Testmethod(structure* aa)
C#代码
fixed (SampleStructure* pArray = dataInformation)
{
ret = Testmethod(pArray);
}
方法 2: 如果我更改 c++ 代码,则可以工作。但我无法更改 C++ 代码。这不是我的代码。
C++代码
__declspec(dllexport)short Testmethod(structure Getcsharpval[], int size)
c#代码
public unsafe static extern short Testmethod([MarshalAs(UnmanagedType.LPArray,SizeParamIndex=3)] SampleStructure[] array);
SampleStructure[] data= new SampleStructure[3] { new SampleStructure { ps = 26 }, new SampleStructure { ps = 27 }, new SampleStructure { ps = 28 } };
ret = Testmethod( data);
我认为你的 c 函数有错误的原型。 尝试:
_declspec(dllexport)short Testmethod(structure* aa)
{
if (aa != 0
&& aa[0].ps == 26 && aa[1].ps == 27)
{
return 1;
}
return 0;
}
在您的 C# 示例中,您有一个结构数组。该数组是引用类型,您更正需要固定内存。该数组是值类型(并且不需要引脚)的结构内存中的序列。所以在数组中你没有指针,而是直接的结构。
您需要将 IntPtr[]
传递给 C++ 代码。
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern short Testmethod(IntPtr[] aa)
分配一个 IntPtr[]
数组并填充它。通过固定每个结构并使用固定对象的地址来执行此操作。或者使用 Marshal.StructureToPtr
。如果使用后者,则必须在调用后释放非托管内存。
好的,我通过使用以下代码创建指向结构指针的指针来解决。
[DllImport("Wrapper.dll", CallingConvention = CallingConvention.StdCall)]
public unsafe static extern short Testmethod (SampleStructure** passstructurepointer);
unsafe
{
fixed(SampleStructure** p2p = new SampleStructure*[3])
{
for (short i = 0; i < 3; i++)
{
var a = stackalloc SampleStructure[1];
a->ps = i;
p2p[i] = a;
}
var s= Testmethod(p2p);
}
}