注意:最终的工作解决方案是在编辑之后!将结构从非托管C++传递到C#
我希望有人能帮我解决我过去几天一直试图解决的问题。
我想从一个非托管的C++ DLL传递一个结构到一个C#脚本。这是我到目前为止有:
C++
EXPORT_API uchar *detectMarkers(...) {
struct markerStruct {
int id;
} MarkerInfo;
uchar *bytePtr = (uchar*) &MarkerInfo;
...
MarkerInfo.id = 3;
return bytePtr;
}
C#
[DllImport ("UnmanagedDll")]
public static extern byte[] detectMarkers(...);
...
[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)]
public struct markerStruct
{
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(0)]
public int Id;
}
...
markerStruct ByteArrayToNewStuff(byte[] bytes){
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
markerStruct stuff = (markerStruct)Marshal.PtrToStructure(
handle.AddrOfPinnedObject(), typeof(markerStruct));
handle.Free();
return stuff;
}
...
print(ByteArrayToNewStuff (detectMarkers(d, W, H, d.Length)).Id);
的问题是,这个工作,但打印的值是完全关闭(有时它打印约400,有时最大int值)。
我在猜测,我在C#中编组结构时出了问题。有任何想法吗?
编辑:
这是工作溶液使用参考:
C++
struct markerStruct {
int id;
};
...
EXPORT_API void detectMarkers(... , markerStruct *MarkerInfo) {
MarkerInfo->id = 3;
return;
}
C#
[DllImport ("ArucoUnity")]
public static extern void detectMarkers(... ,
[MarshalAs(UnmanagedType.Struct)] ref MarkerStruct markerStruct);
...
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct MarkerStruct
{
public int Id;
}
...
detectMarkers (d, W, H, d.Length, ref markerInfo);
print(markerInfo.Id);
我试过使用ref,但是我仍然没有设法获得正确的值......你可能看看我编辑的问题吗? – mkolarek
@kolarek:就像我在我的回答中所说的,当你使用'ref'或'out'关键字时,C#实际上会传递一个指针。因此,在C++端使用'void detectMarkers(/*...*/ markerStruct * MarkerInfo)',然后使用'MarkerInfo-> id = 3;'。此外,摆脱p/invoke签名中的'In'属性,这意味着不从C++获取数据,这显然与您想要的相反。 –
非常感谢,我已经完成了! – mkolarek