序文
ワークプロセスは、必然的に混合プログラミングに遭遇し、そして今、私たちは、C ++やC#プログラミング言語についてお話したいと思います。COM技術とプラットフォーム呼び出し(P / Invoke):主に2つの方法で利用できる存在するC#C ++ライブラリを呼び出します。今、私たちは技術を起動します/ Pについてお話したいと思います。
まず、プラットフォーム呼び出し
技術プラットフォームの呼び出しがアンマネージ関数(DLL)は、このようなDLL Win32のDLLとC / Cとして、実装++作成し、マネージコードでDLLを呼び出すことができます使用してください。何人かの友人には疑問を持っている必要があり、ここを参照してください - 私たちはどのような状況で使用することができます
テクノロジープラットフォームは、ダイナミックリンクライブラリアンマネージ関数を呼び出すために呼び出しますか?
.NET APIは、我々はシステムへのアクセスが、包括されていない、私の一般的な操作、システムのいくつかは私たちのために呼び出しをカプセル化し、我々はまた、システムにアクセスするための独自のAPIを必要としています。
ドッキング時に、このようなCを使用して、スクリーンショット、基板の処理、などの一部のプログラムは、/ C ++には大きな利点は、特に、および他の会社の製品を持っています。
マネージドコードは、効率を向上させるために、今回もマネージコードのCライブラリ関数呼び出しで考慮することができるように効率的アンマネージコード、ではありません。
プラットフォーム呼び出しのステップ
(1)取得した情報アンマネージ関数、DLLの名前は、アンマネージ関数名やその他の情報を呼び出します
(2)。プラットフォームを呼び出して、マネージコードでアンマネージ関数を宣言し、追加のプロパティが必要
(3)第二工程で直接管理機能の中で宣言マネージコードを呼び出します
呼び出し元のプロセスプラットフォーム呼び出し
(1)(ローカルアイデンティティ必要DLLIMPORTの関数宣言を)機能が含まれているDLLを探します
(2)メモリにロードされたDLLを見つけることができます。
(3)関数のパラメータメモリ内のアドレスを見つけるために、必要なデータをマーシャリングするために、スタックにプッシュ。CLRときにのみのみDLLを見つけてロードするための最初の呼び出し、およびメモリ内のアドレス検索機能。CLRアドレスが機能をキャッシュされます後に関数が一度呼び出されると、このメカニズムは、効率CLRプラットフォーム呼び出しを向上させることができます。アプリケーションドメインに先立って、アンロードされるメモリ内のDLLを発見されています。
(4)管理されていない機能を実行します。
2、C / C ++ライブラリの構築
注意:C#は、直接C ++クラスを呼び出していない、我々はC ++クラスを記述し、C / C ++の方法、外国暴露によるC関数にパッケージ化することができます。簡単にするために、唯一の次のCの関数。
1、我々は選択した新規プロジェクト(C ++、ダイナミックリンクライブラリ)
他の依存関係があるかもしれないので2は、空のプロジェクトを選択しないでください
3、付属するサンプルコードを削除して、我々は(コールバックメソッドを添付)、独自のインターフェースを追加します
#ifdefのADDDLL_EXPORTS の#define ADDDLL_API __declspec(DLLEXPORT) の#else の#define ADDDLL_API __declspec(DLLIMPORT) #endifの typedefの空隙(__stdcall * RecvDataCallback)(符号なし文字 * pDataを、INT iDataSize、INT iMsgType、長いlContext)。 長い mCallBackFunction = NULL; EXTERN_C ADDDLL_API INT(追加をint、int型のB)。 EXTERN_C ADDDLL_API BOOL MLogin(長い lInstance、ULONG pServerIP、int型 iConferenceNo、長いですpCallBackFunction、長いlContext)。 EXTERN_C ADDDLL_API BOOL MLogout(ロングlInstance)。 EXTERN_C ADDDLL_API BOOL MSendData(長い lInstance、符号なしのchar * pDataを、int型 iDataSize、int型iMsgType)。 空 logPrintf(のconst char型 *文字列);
達成するためのcppファイル
// AddDll.cpp:エクスポート機能のカスタムDLLアプリケーション。 // の#include " STDAFX.H " の#include " AddDll.h " INT追加(int型 A、int型B) { 戻り A + B; } ADDDLL_API BOOL MLogin(ロング lInstance、ULONG pServerIP、int型 iConferenceNo、ロング pCallBackFunction、ロングlContext ) { STD :: 文字列 strlog = " ログインからログ:\のR&LT \ N- " ; strlog + =" lInstance:" + のstd :: to_stringに(lInstance)。 strLog + = " pServerIP:" + のstd :: to_stringに(pServerIP)。 strLog + = " iConferenceNo:" + のstd :: to_stringに(pServerIP)。 strLog + = " pCallBackFunction:" + のstd :: to_stringに(pCallBackFunction)。 strLog + = " lContext:" + のstd :: to_stringに(lContext)。 strLog + = " \ rをする\ n " 。 logPrintf(strLog。 mCallBackFunction = pCallBackFunction。 返す 真; } ADDDLL_API BOOL MLogout(長いlInstance) { のstd :: 文字列 strLogは= " ログアウトからログ:\ R \ n " 。 strLog + = " lInstance:" + のstd :: to_stringに(lInstance)。 strLog + = " \ rをする\ n " 。 logPrintf(strLog.c_str())。 返す 真; } ADDDLL_API BOOL MSendData(ロングlInstance、符号なしのchar * pDataを、INT iDataSize、INT iMsgType) { のstd :: 文字列 strLog = " のsendDataからログ:\ R \ n " 。 strLog + = " lInstance:" + のstd :: to_stringに(lInstance)。 strLog + = " pDataを:" +のstd :: 文字列((のconst char型 * )pDataを)。 strLog + = " iDataSize:" + のstd :: to_stringに(iDataSize)。 strLog+ = " iMsgType:" + のstd :: to_stringに(iMsgType)。 strLog + = " \ rをする\ n " 。 logPrintf(strLog.c_str())。 ( *(RecvDataCallback)mCallBackFunction)((符号なしのchar *)pDataを、strlenを((CONST のchar *)pDataを)、iMsgType、0 ); 返す 真; } ボイド logPrintf(CONST のchar *のSTR) { FILE *とのFP =用のfopen(" D:\\ log.txtという"、" + " )。 もし(FP) { fprintfの(FP、STR)。 FCLOSE(FP)。 } }
世代へ
4.これは、依存関係があるかもしれないので、それはあなたが空のプロジェクトを選択することができますC ++を呼び出すことであれば、空のプロジェクトをチェックしていないに注意すべきです
エクスポートのロゴを忘れないようにしてください
extern "C" __declspec(のdllexport)
を参照してくださいポイント私はだった
3、C#の側のコール
/// <要約> /// 注意:需要类中声明、方法新しい中、避免被回收 /// </要約> /// <PARAM NAME = "pDataを"> </ param>の /// <PARAM NAME = "iDataSize"> </ PARAM> /// <PARAM NAME = "iMsgType"> </ PARAM> /// <PARAM NAME = "lContext"> </ PARAM> [UnmanagedFunctionPointer(CallingConvention.Cdecl)] パブリック デリゲート 空 RecvDataCallback(のIntPtr pDataを、int型 iDataSize、int型 iSendMsgType、int型 iCallBackMsgType、長いlContext)。 パブリック 静的 クラスCRelay { 公共の 静的INT32 lInstance = 0 。 [DLLIMPORT(" RelayDllR.DLL "、エントリーポイント= " のCreateInstance "、SetLastError = 真、項目CharSet = CharSet.Unicode、ExactSpelling = 真、CallingConvention = CallingConvention.Cdecl)] パブリック 静的 にextern のInt32のCreateInstance()。 [DLLIMPORT(" RelayDllR.DLL "、エントリーポイント= " DestroyInstance "、SetLastError = 真、項目CharSet = CharSet.Unicode、ExactSpelling = 真、CallingConvention =CallingConvention.Cdecl)] パブリック 静的 にextern 無効DestroyInstance(のInt32 lInstance)。 [DLLIMPORT(" RelayDllR.DLL "、エントリーポイント= " ログイン"、SetLastError = 真、項目CharSet = CharSet.Unicode、ExactSpelling = 真、CallingConvention = CallingConvention.Cdecl)] パブリック 静的 にexternの ブールログイン(のInt32 lInstance、UInt32型pServerIP、のInt32 iConferenceNo 、/ * RecvDataCallback * / のInt32 pCallBackFunction、のInt32 lContext)。 [DLLIMPORT("RelayDllR.DLL "エントリーポイント= " ログアウト"SetLastError = 真、項目CharSet = CharSet.Unicode、ExactSpelling = 真、CallingConvention = CallingConvention.Cdecl)] パブリック 静的 にexternの ブールログアウト(のInt32 lInstance); [DLLIMPORT(" RelayDllR.DLL "、エントリーポイント= " のSendData "、SetLastError = 真、項目CharSet = CharSet.Unicode、ExactSpelling = 真、CallingConvention = CallingConvention.Cdecl)] パブリック 静的 にextern BOOLのSendData(のInt32 lInstance、[MarshalAs(UnmanagedType.LPArray)] バイト [] pDataを、のInt32 iDataSize、のInt32 iMsgType)。
注意:文が[UnmanagedFunctionPointer(CallingConvention.Cdecl)]以下の良好なことができない、またはそれが唯一のコールで、プラットフォームのリリース後のコールの限られた数であってもよいコールバックは、クラス宣言で(回収されるGCを避けるために)初期化する必要があり、方法。