Uwaga: Ostateczne rozwiązanie robocze jest po edycji!Przekazywanie struktury z niezarządzanego C++ do C#
Mam nadzieję, że ktoś może mi pomóc z problemem, który próbowałem rozwiązać przez ostatnie kilka dni.
Próbuję przekazać struct z niezarządzanego DLL C++ do skryptu C#. To, co mam tak daleko:
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);
Problemem jest to, że to działa, ale wartość drukowana jest całkowicie wyłączony (czasami drukuje to około 400, czasami maksymalna wartość int).
Zgaduję, że jest coś złego w tym, w jaki sposób przygotowałem strukturę w C#. Jakieś pomysły?
Edit:
Jest to roztwór roboczy przy użyciu 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);
Próbowałem użyć ref, ale nadal nie udało mi się uzyskać właściwej wartości ... Czy mógłbyś rzucić okiem na moje zmodyfikowane pytanie? – mkolarek
@kolarek: Tak jak powiedziałem w mojej odpowiedzi, kiedy użyjesz słowa kluczowego 'ref' lub' out' C# faktycznie przekaże wskaźnik. Tak więc użyj 'void detectMarkers (/ *...*/ markerStruct * MarkerInfo)' po stronie C++, a następnie 'MarkerInfo-> id = 3;'. Należy również pozbyć się atrybutu 'In' w sygnaturze p/invoke, co oznacza, że nie odzyskasz danych z C++, co oczywiście jest przeciwieństwem tego, co chcesz. –
Dziękuję bardzo, mam go uruchomione! – mkolarek