C# での C++ DLL のデバッグ

 

C# によって呼び出される DLL は、通常、
extern "C" __declspec(dllexport)
BOOL Integrate3 (){...} など、エクスポートされた関数を呼び出す前に適切な形式で提示する必要があるだけです。このような関数は、C# では次のように宣言されます。

[DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
        public static extern bool Integrate3();、ここでの呼び出しは比較的単純で、一部のデータ型は MarshalAs Type 変換を通じて管理する必要があります。のような:

extern "C" __declspec(dllexport)
BOOL Integrate (LPCWSTR file1, LPCWSTR file2, LPCWSTR OutputFile){...}

データ型が統一されていないため、宣言時に型変換に注意する必要があります。

[DllImport("xxx.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
        public static extern bool Integrate([In, MarshalAs(UnmanagedType.LPWStr)]string file1,
            [In, MarshalAs(UnmanagedType.LPWStr) ]文字列 file2, [In、MarshalAs(UnmanagedType.LPWStr)]文字列出力ファイル);

この方法で呼び出すことに基本的に問題はありません。焦点はデータ型の変換にあります。何度か試してみると問題ありません。

もう 1 つの小さな実践的な経験は、C# で C++ DLL をデバッグすることです。知っていれば数語で済みますが、知らなければ、長い時間がかかります。C# プロジェクトのプロパティの「デバッグ項目を有効にする」で、の 1 つの項目:「アンマネージ コードのデバッグを有効にする」、これをフックすると、通常のプログラムをデバッグするときと同じように、すべてがうまくいきます。

C# が C++ DLL を呼び出す場合、パラメーターの受け渡しが問題になります。今日遭遇した問題は、C++ でエクスポートされた関数のパラメーターが文字列型であることです。C# で文字列パラメーターを通じて呼び出すと、メモリが破損しているか読み取れないという例外メッセージが表示されます。その後、C++ エクスポート関数のパラメーターを string から LPTSTR 型、つまり char* 型に変更し、さらに C# の対応するパラメーターを StringBuilder 型に変更しました。これにより、パラメーターの受け渡しの問題が解決されただけでなく、渡されたパラメータの問題。

DllImport の知識の拡張: DllImport 
 .net Framework プログラムは、静的 DLL エントリ ポイントを通じてネイティブ コード ライブラリにアクセスできます。DllImport 属性は、外部メソッドの実装を含む DLL の場所を指定するために使用されます。

DllImport 属性は次のように定義されます:
  
namespace System.Runtime.InteropServices
{
 [AttributeUsage(AttributeTargets.Method)]
 public class DllImportAttribute: System.Attribute
 {
  public DllImportAttribute(string dllName) {...}
  public CallingConvention CallingConvention;
  public CharSet CharSet;
  public string EntryPoint ;
  public bool ExactSpelling;
  public bool PreserveSig;
  public bool SetLastError;
  public string Value { get {...} } } }
 注
:
  
  1.
  
 DllImport はメソッド宣言にのみ配置できます。 
    2. DllImport には 1 つの位置決めパラメーターがあります。インポートされたメソッドの DLL 名を含む dllName パラメーターを指定します。 
    3. DllImport には 5 つの名前付きパラメータがあります。
     a. CallingConvention パラメータは、エントリ ポイントの呼び出し規則を示します。CallingConvention が指定されていない場合は、デフォルト値の CallingConvention.Winapi が使用されます。
     b. CharSet パラメータは、エントリ ポイントで使用される文字セットを示します。CharSet が指定されていない場合は、デフォルト値の CharSet.Auto が使用されます。
   c. EntryPoint パラメータは、DLL 内のエントリ ポイントの名前を指定します。EntryPoint が指定されていない場合は、メソッド自体の名前が使用されます。
   d. ExactSpelling パラメータは、EntryPoint が、指定されたエントリ ポイントのスペルと正確に一致する必要があるかどうかを示します。ExactSpelling が指定されていない場合は、デフォルト値の false が使用されます。
   e. PreserveSig パラメータは、メソッドの署名を保存するか変換するかを示します。署名が変換されると、HRESULT 戻り値と、その戻り値に対する retval という名前の追加出力パラメーターを持つ署名に変換されます。PreserveSig が指定されていない場合は、デフォルト値の true が使用されます。
      f. SetLastError パラメーターは、メソッドが Win32 の「最後のエラー」を保持するかどうかを示します。SetLastError が指定されていない場合は、デフォルト値の false が使用されます。 
 4. これは 1 回限りの属性クラスです。
 5. さらに、DllImport 属性で変更されたメソッドには extern 修飾子が必要です。

以下は、C# で Win32 MessageBox 関数を呼び出す例です:
  
using System;
using System.Runtime.InteropServices;
class MainApp
{

     //DllImport を通じて user32.dll クラスを参照します。MessageBox は user32.dll クラスからのものです
 [DllImport("user32.dll", EntryPoint="MessageBox")]
 public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);
 public static void Main()
 {
  MessageBox (0, "Hello, this is PInvoke!", ".net", 0 ); } }
 ほとんど
すべて
のオブジェクト指向プログラミング言語は、抽象クラスの概念を使用しています。抽象クラスは、抽象的なものを実装するためのより高い柔軟性を提供します。セックス。C# も例外ではなく、C# は仮想インターフェイスをカバーする技術を通じて抽象クラスの適用を深めます。これについて詳しくは、次のセクション「仮想インターフェイスのオーバーライド」を参照してください。

ここで議論するのは、C# が標準ダイナミック ライブラリを呼び出す問題です。前のドキュメントで述べたように、C# は Win32API を呼び出します。原理は同じです。ここでは、C で標準ダイナミック ライブラリを作成して、 C# と呼んでください (この記事は初心者向けで、途中に冗長なコードがなく、簡潔で明瞭です)
ソフトウェア環境: VC6.0 (もちろん VC5 の他のバージョンも利用可能です)
1. 標準の動的コードを作成します。図書館


__declspec(dllexport) int __cdecl add(int, int);//この文は、ダイナミック ライブラリが外部から呼び出すことができる関数プロトタイプを出力することを宣言します。
int add(int a, int b) {//この関数を実装します
return a+ b ;
}


上記の単純な 3 行のコードは、add メソッドを宣言します。入力パラメータは 2 つの int パラメータで、2 つの数値の合計が返されます。MyLib.c として保存し、コンパイル コマンドを実行します。H:/XSchool/C#
-School
/ HowTo>cl /LD MyLib.c
Microsoft (R) 32 ビット C/C++ 最適化コンパイラ バージョン 12.00.8168 (80x86 用)
Copyright (C) Microsoft Corp 1984-1998.All Rights Reserved.

MyLib.c
Microsoft (R) インクリメンタル リンカー バージョン 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. 無断転載を禁じます。

/out:MyLib.dll
/dll
/implib:MyLib.lib
MyLib.obj
   ライブラリ MyLib.lib とオブジェクト MyLib.exp を作成する

コンパイルによって動的ライブラリが正常に生成されたことを示す上記の出力があることを確認します。

2. System
;
using System.Runtime.InteropServices;//これは、DllImport を使用するときに導入されるパッケージです。

public class InvokeDll { [DllImport("MyLib.dll", CharSet=CharSet.Auto)] static extern int add(int a, int b);//Win32API と同じ外部標準動的ライブラリを宣言します。

public static void Main() { Console.WriteLine(add(10,30)); } }これを InvokeDll.cs ファイルとして保存し、 MyLib.dllと同じディレクトリに配置して、ファイルをコンパイルします。C#-School/HowTo>csc invokedll.csにより Invokedll.exe が生成され、実行できます。





おすすめ

転載: blog.csdn.net/dj1232090/article/details/3985215