Lưu ý: Giải pháp làm việc cuối cùng là sau khi chỉnh sửa!Chuyển cấu trúc từ C++ không được quản lý đến C#
Tôi hy vọng ai đó có thể giúp tôi giải quyết vấn đề tôi đã cố gắng giải quyết trong vài ngày qua.
Tôi đang cố chuyển cấu trúc từ một tệp DLL C++ không được quản lý sang tập lệnh C#. Đây là những gì tôi có cho đến nay:
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);
Vấn đề là làm việc này, nhưng giá trị in là hoàn toàn tắt (đôi khi nó in khoảng 400, đôi khi giá trị int tối đa).
Tôi đoán rằng có điều gì đó sai với cách tôi sắp xếp cấu trúc trong C#. Bất kỳ ý tưởng?
Edit:
Đây là giải pháp làm việc sử dụng 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);
Tôi đã cố gắng sử dụng ref, nhưng tôi vẫn chưa quản lý để có được giá trị đúng ra ... Bạn có thể có thể có một cái nhìn tại câu hỏi đã chỉnh sửa của tôi? – mkolarek
@kolarek: Giống như tôi đã nói trong câu trả lời của tôi, khi bạn sử dụng từ khóa 'ref' hoặc' out' C# sẽ thực sự vượt qua một con trỏ. Vì vậy, sử dụng 'void detectMarkers (/*...*/ markerStruct * MarkerInfo)' trên phía C++, và sau đó là 'MarkerInfo-> id = 3;'. Ngoài ra, loại bỏ thuộc tính 'In' trong ký tự p/invoke, điều đó có nghĩa là không lấy lại dữ liệu từ C++, mà rõ ràng là ngược lại với những gì bạn muốn. –
Cảm ơn bạn rất nhiều, tôi đã có nó và chạy! – mkolarek