![](/img/trans.png)
[英]SafeArrayTypeMismatchException when passing c# struct to unmanaged C++ DLL
[英]Passing struct from unmanaged C++ to 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#中编组结构的方式有问题。 有任何想法吗?
编辑:
这是使用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 ++代码就可以填充它。
MarkerInfo变量是本地变量,在函数返回时超出范围。 不要返回指向局部变量的指针,它们指向的对象将不再存在。
要为这个帖子提供一个旋转... thx ...
// new struct and generic return for items to
struct _itemStruct
{
unsigned int id; // 0 by default, so all lists should start at 1, 0 means unassigned
wchar_t *Name;
};
// for DLL lib precede void with the following...
// EXPORT_API
void getItems(std::vector<_itemStruct *> *items)
{
// set item list values here
//unsigned char *bytePtr = (unsigned char*)&items; // manual pointer return
return;
};
/* // In theory c# code will be...
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct _itemStruct
{
public unsigned int Id;
public string Name;
}
[DllImport ("ListOfItems")] // for ListOfItems.DLL
public static extern void getItems(
[MarshalAs(UnmanagedType.Struct)] ref List<_itemStruct> items);
// */
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.