1

メソッド「Foo()」を持つC++DLL「TheFoo.dll」があります

次のコマンドを呼び出すだけで、このメソッドを使用する他のC++コードにアクセスできます。

Foo();

私はメソッドが持っていると信じています:

 __declspec( dllexport )

したがって、P / Invokeについて読んだことで、C#コードから同じメソッドを簡単に呼び出すことができるはずだと思いました。

namespace PInvokeExample1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

        }


        [DllImport(@"C:\MyFolder\TheFoo.dll")]
        public static extern
            void Foo();

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            Foo();

        }



    }
}

実行すると、エラーが発生します。

Unable to find an entry point named 'Foo' in DLL 'C:\MyFolder\TheFoo.dll'.

なぜそれが見つからないのか、何か考えはありますか?

4

3 に答える 3

10

C++ 言語は、C# と同様にオーバーロードをサポートしています。void Foo(int)関数と関数をエクスポートできますvoid Foo(double)。明らかに、これら 2 つの関数を両方とも "Foo" としてエクスポートすることはできず、DLL のクライアントはどちらを選択すればよいかわかりません。そうではありません。

C++ コンパイラは、関数の名前を装飾することでこの問題を解決します。Foo(int) を Foo(double) とは異なるものにする余分な文字を追加します。これらの装飾されDumpbin.exe /exports foo.dllた名前は、エクスポートされた関数の名前を一覧表示する Visual Studio コマンド プロンプトから実行することで確認できます。宣言が適切であると仮定すると、 が表示されます?Foo@@YAXXZ

したがって、C# プログラムでの対応する宣言は次のようになります。

    [DllImport("foo.dll", EntryPoint = "?Foo@@YAXXZ", 
               ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
    private static extern void Foo();

C++ の関数宣言を変更して、C# の宣言を簡単にする方法があります。これは実際には良い考えではありません。これらの装飾された名前は実際に間違いを見つけるのに役立ちます。

于 2012-09-26T00:19:46.467 に答える
4

C++ に関する詳細情報を提供する必要があります。extern "C" __declspec(dllexport)代わりに使用してみてください。C++ は奇妙な名前でエクスポートされるため、使用するとそれextern "C"が回避されます。

于 2012-09-25T22:39:52.077 に答える
1

dll で extern "C" と宣言していない場合、その名前はおそらく "マングル" されています。Dependency Walker などを使用して、dll がエクスポートするシンボルを確認できます。

于 2012-09-25T22:40:06.460 に答える