注意:最终的工作解决方案是在编辑之后!
我希望有人能帮助我解决过去几天我一直在努力解决的问题。
我正在尝试将结构从非托管 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# 中编码结构的方式有问题。有什么想法吗?
编辑:
这是使用 ref 的工作解决方案:
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 );
最佳答案
您正在返回一个指向局部变量的指针,该变量在 .NET 可以读取之前已被销毁。这在纯 C++ 中是个坏主意,在 p/invoke 中也是个坏主意。
相反,让 C# 传递一个指向结构的指针(只需使用 ref
关键字),C++ 代码只需填充它即可。
关于c# - 将结构从非托管 C++ 传递到 C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18519729/