2011-06-17 31 views
0

私はC#アプリケーションで使用したいこのC .dllソースコードを持っています。 DllImportsの束をする代わりに、私はC++/CLIでそのためのラッパーを書くことに決めました。C++のC++/CLIラッパー

私のCの関数は、その中に4つのコールバック関数と構造体へのポインタを取ります。

typedef struct 
{ 
PFN_IN readFp; 
PFN_OUT writeFp; 
}OPEN_ARGS; 

C++/CLIは同じ.hファイルを共有し、したがって、同じのtypedefを使用しています。

C#コードには、C#プロジェクトに.hを付けることができないため、この構造体の独自の定義とCBの代理人があります。だから、

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate Int32 PFN_OUT(IntPtr arg, IntPtr pSrc, Int32 len); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct OPEN_ARGS 
    { 
     public PFN_IN readFp; 
     public PFN_OUT writeFp; 
    }; 

、私はC++/CLIを追加するときに、明示的にC#のプロジェクトの参照に、++/complilerは

"Error 2 Argument 2: cannot convert from 'WrapperTest.Program.OPEN_ARGS' to 'SAR_OPEN_ARGS'" 

を言っC++/CLI関数の呼び出しを受け入れないだろう。しかし、私はCが含まれている場合、DLL CLIは、暗黙的にその

[DllImport("Wrapper.dll", CharSet = CharSet.Auto, EntryPoint = "[email protected]@[email protected]@@Z")] 
public static extern int CLIOpen(int a, OPEN_ARGS args); 

のようにそれだけで正常に動作しますDLL。

このタイプのキャストエラーを無視するようにC#コンパイラに指示する方法はありますか、またはCコード関数をラップする方法は他にありますか?

EDIT:より良いreadabiltiy

答えて

4

あなたはこれをしなかった場合は別の方法。 C DLLとC#アセンブリ間の相互運用性を処理するC++/CLI DLLがあるため、同等のAPIが公開され、より多くの.NET風の概念のみが使用されます。

たとえば、構造体を関数ポインタで公開する代わりに、3つのイベントを持つクラスを公開することができます。 C#アセンブリは、これらのイベントのハンドラを追加します。 C++ DLLの内部では、C DLLが期待する関数ポインタを使用しますが、その実装によってC#アセンブリが処理している.NETイベントが発生します。

これは、C#側でDLLを使用する方がはるかに優れたエクスペリエンスを提供し、発生しているinteropコンパイラのエラーを取り除く可能性があります。

+0

提案していただきありがとうございます。良いアイデアのように聞こえる。 ps。何らかの理由で私はあなたの投稿をアップアップすることはできません: – fl0sT

0

のための変数名をクリーンアップし、すべてのあなたのPInvokeのラッパーコードを生成するためにSWIGを使用することを検討してください。

http://www.swig.org/Doc1.3/CSharp.html

+0

次に、あなたのような何かを行うことができます。 –

0

管理対象のC++では、pInvokeの代わりに#pragma managed/unmanagedコンパイラ指令を使用することができます。これは使用しているように見えます。次に、同じCPPファイルであっても、管理されたコードとネイティブコードを同じアセンブリにコンパイルすることができます。私の人生はそれに依存している場合、私はガブガブ飲むを考えていない

#pragma managed 
// include your native headers here 
#include "foo.h" // whatever you call it. 

#using <System.dll> // what ever else you need here... 

// Have to wrap a function in a class, since .NET doesn't allow free standing functions. 
public ref class foo 
{ 
public static int sarCLIOpen(int a, SARWrapperTest::Program::SAR_OPEN_ARGS args) 
{ 
// do something to convert your managed args to native args. 
::SAR_OPEN_ARGS native_args = ... 
// then call your native function 
return sarCLIOpen(a, native_args); 
} 

}; 
+0

これはまさにあなたを理解すれば、私がやっていることです。私は自分の.cと.hソースコードをC++/CLIプロジェクトに含まれているオリジナルのC DLLから持っています。私はこのプロジェクトを別のdllとしてコンパイルしています。これは私のC#アプリケーションで使いたいものです。 – fl0sT

+0

自分の管理対象メソッドの関数シグニチャーにも注意してください。それは管理されたSAR_OPEN_ARGSを取ります...これはあなたがやっていることですか?ネイティブの型は、上記のコンパイラエラーに従っているように見える管理されたパラメータリストに公開することはできません。 –

+0

確かに、私はそれが有効な提案だと思っていますが、WrapperTest :: Program :: OPEN_ARGSをC#アプリではなくラッパーで宣言するのは意味があります。 あなたのご意見ありがとうございます。 – fl0sT