あなたの例には、期待通りに動作させるために解決しなければならないいくつかの問題があります。まずはあなたの目標は、パラメータを介してC void returns関数で設定されたCタイプsize_t
の値を取得することです。
C#とCの両方の値へのポインタを使用するか、C#パラメータの引き渡しを強制するC#パラメータ修飾子(ref
またはout
)の組み合わせを使用すると、パラメータ経由で値を取得するという簡単な問題が解決されます。ポインタとCのポインタ、次のように関数のシグネチャは次のようになります
// Implementation with pointers
[DllImport("MyC.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true, EntryPoint = "Func")]
public static extern unsafe void CSharpFuncPtr(UIntPtr* x);
// Implementation with parameter modifiers - ref can be raplaced by out
[DllImport("MyC.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true, EntryPoint = "Func")]
public static extern void CSharpFuncMod(ref UIntPtr x); //
// C function implementation
void Func(size_t* x) { *x = 7; }
マーシャリング中に解決されなければならない第二のさらに重要な問題は、C型などのネイティブサイズの符号なし整数size_t
の使用です。 x86アーキテクチャでは32ビットの符号なし整数、x64アーキテクチャでは64ビットの符号なし整数のいずれかと定義されています(他のすべてのプロセッサアーキテクチャを意図的にスキップします)。 .NET型システムでは、ネイティブサイズの整数型がありません。この問題を回避するには、マネージタイプのシステムでsize_t
をエミュレートするために、管理された符号なしポインタタイプUIntPtr
を使用します。
。NETチームはこの制限を認識しており、いわゆるネイティブ整数の実装に関する議論や計画があります - 参照:Support natural size data types in the CLR
[DllImport("MyC.dll", CallingConvention = CallingConvention.Cdecl, PreserveSig = true, EntryPoint = "Func")]
public static extern void CSharpFuncNativeInt(ref nuint x);
最後に表面に簡単であると思われる問題は、そのすべての後に、シンプルで簡単なものではなく、エレガントなソリューションには、.NETランタイムとBCLライブラリの変更が必要です。
「void」メソッドからx = 8を返すと誤解されていない場合は、正しいデータ型を返すためにc関数の戻り値の型を変更できますか? – MethodMan
ポインタとリファレンスについて読む。 – tkausl
cコードは渡された値を変更せず、コピーのみを変更します。 – ROX