注:最終的な解決策は編集後です!アンマネージ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の周りに出力します。これは私がこれまでにしたものですmax int value)を返します。
私は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);
私はrefを使用しようとしましたが、私はまだ適切な価値を得ることができませんでした...私の編集した質問を見てもらえますか? – mkolarek
@kolarek:私の答えで言ったように、 'ref'または' out'キーワードを使うとC#は実際にポインタを渡します。ですから、C++側で 'void detectMarkers(/*...*/markStruct * MarkerInfo)'を使い、 'MarkerInfo-> id = 3;'を使ってください。また、p/invokeシグネチャの 'In'属性を取り除きます。これは、C++からデータを取得しないことを意味します。これは明らかにあなたが望むものの反対です。 –
ありがとう、私はそれを稼働している! – mkolarek