C#P \ Invoke DLL没有进入C ++的入口点?

时间:2012-09-25 22:36:15

标签: c# pinvoke dllimport

我有一个C ++ Dll“TheFoo.dll”,方法是“Foo()”

我可以通过简单地调用:

来访问使用此方法的其他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'.

为什么找不到它的任何想法?

3 个答案:

答案 0 :(得分:9)

C ++语言支持重载,就像C#一样。您可以导出函数void Foo(int)和函数void Foo(double)。很明显,这两个函数不能同时导出为“Foo”,DLL的客户端不知道选择哪一个。所以事实并非如此。

C ++编译器通过装饰函数的名称解决了这个问题。添加额外的字符使Foo(int)与Foo(double)不同。您可以通过从Visual Studio命令提示符运行Dumpbin.exe /exports foo.dll来查看这些修饰名称,其中列出了导出函数的名称。假设您的声明相关,您会看到?Foo@@YAXXZ

因此,C#程序中的相应声明应为:

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

有一些方法可以更改C ++函数声明,使C#声明更容易。这实际上不是一个好主意,这些装饰名称实际上有助于捕捉错误。

答案 1 :(得分:4)

您应该提供有关C ++的更多信息。请尝试使用extern "C" __declspec(dllexport)。 C ++使用奇怪的名称导出,因此使用extern "C"可以避免这种情况。

答案 2 :(得分:1)

如果你没有在你的dll中声明它是外部“C”,它的名字很可能被“破坏”了。您可以使用Dependency Walker之类的东西来查看您的dll导出的符号。