注意:最終的工作解決方案是在編輯之後!將結構從非託管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