Hinweis: Die endgültige Arbeitslösung ist nach der Bearbeitung!Passing Struktur von nicht verwalteten C++ C#
Ich hoffe, dass mir jemand mit einem Problem helfen kann ich für die letzten paar Tage zu lösen versucht habe.
Ich versuche, eine Struktur aus einem nicht verwalteten C++ DLL in eine C# Skript zu übergeben. Das ist, was ich habe, so weit:
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);
Das Problem ist, dass dies funktioniert, aber der Wert gedruckt ist vollständig ausgeschaltet (manchmal druckt es rund 400, manchmal max int Wert).
Ich vermute, dass es etwas falsch mit, wie ich die Struktur in C# gemarshallt. Irgendwelche Ideen?
Edit:
Dies ist die Arbeitslösung mit 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);
Ich habe versucht, Ref zu verwenden, aber ich habe es immer noch nicht geschafft, den richtigen Wert herauszubekommen ... Könnten Sie sich vielleicht meine bearbeitete Frage ansehen? – mkolarek
@kolarek: Wie ich in meiner Antwort sagte, wenn Sie das 'ref' oder' out' Schlüsselwort verwenden, wird C# tatsächlich einen Zeiger übergeben. Verwenden Sie 'void detectMarkers (/*...*/markerStruct * MarkerInfo)' auf der C++ - Seite und dann 'MarkerInfo-> id = 3;'. Entfernen Sie auch das 'In'-Attribut in der p/invoke-Signatur, das bedeutet, dass Sie keine Daten aus C++ zurückholen, was offensichtlich das Gegenteil von dem ist, was Sie wollen. –
Vielen Dank, ich habe es am Laufen! – mkolarek