5

DLLインポートを使用してC#ライブラリにインポートしているC++ DLLがあるという奇妙な問題があります。エントリ ポイントを指定すると、すべてが期待どおりに機能します。例を次に示します。

internal static class UnsafeMethods
{
    [DllImport("GoodSchool.dll", EntryPoint = @"?AddNum@@YAHHH@Z")]
    public static extern int AddNum(int num1, int num2);
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(UnsafeMethods.AddNum(4,5));
    }
}

ただし、次のような単純化されたインポートを使用すると:

[DllImport("GoodSchool.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int AddNum(int num1, int num2);

おなじみのエラー メッセージが表示されます。

未処理の例外: System.EntryPointNotFoundException: DLL 'GoodSchool.dll' に 'AddNum' という名前のエントリ ポイントが見つかりません

メソッドが適切に公開されていることを確認するために依存関係を使用し、パラメーターと命名規則を確認するために表記法をデコードしました。すべて問題ないようです。

C++ の関数シグネチャは非常に単純です。

  __declspec(dllexport) int AddNum(int num1, int num2); 

装飾された名前を EntryPoint として提供せずに C# でこのメソッドを呼び出す方法について何か提案はありますか? 私は何を間違っていますか?「C」エクスポートを使用したくありません。私の理解では、装飾された関数名は DllImport で使用しても問題ありません。

4

2 に答える 2

7

C++ は、関数名のオーバーロードを考慮して関数名をマングルします。結局のところ、DLL が

__declspec(dllexport) int AddNum(int num1); 
__declspec(dllexport) int AddNum(int num1, int num2); 

どれをAddNum指しますか?

シンボル?AddNum@@YAHHH@Zは、アンマネージ DLL で公開されるマングルされた (装飾された) 名前です。

https://en.wikipedia.org/wiki/Name_mangling#Name_mangling_in_C.2B.2B

あなたの DLL は と呼ばれるものをエクスポートしませんAddNum

于 2013-01-11T03:10:30.253 に答える
6

装飾された関数名はDllImport、実際に実行していることからわかるように、 で使用しても問題ありません。ただし、そのためには、装飾された関数名をインポートで指定する必要があります。装飾されていない名前は、リンカー (静的または動的) に関する限り存在しません。これAddNumは、単にライブラリが公開するシンボルではありません。

代わりに、あなたが求めていることをしたい場合:

EntryPoint として装飾された名前を指定せずに C# でこのメソッドを呼び出しますか?

その場合、そもそも C++ が名前をマングルすることはできません。装飾名を指定する、C++ コードでリンケージをDllImport 使用することができます。extern "C"どちらかを選択する必要があります。

于 2013-01-11T03:13:16.313 に答える