简体   繁体   English

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

[英]C# P\Invoke DLL no entry point into C++?

I have a C++ Dll "TheFoo.dll" with a method "Foo()" 我有一个方法为“ Foo()”的C ++ Dll“ TheFoo.dll”

I have access to other C++ code that uses this method by simply calling: 我可以通过简单地调用以下方法来访问使用此方法的其他C ++代码:

Foo();

I believe the Method does have the: 我相信该方法确实具有:

 __declspec( dllexport )

So, with the reading I've done about P/Invoke, i thought i should be able to simply call the same method from my C# code: 因此,通过阅读有关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();

        }



    }
}

When i run it, i get an error: 当我运行它时,出现错误:

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

Any ideas why it is not found? 为什么找不到它的任何想法?

The C++ language supports overloading, much like C# does. C ++语言支持重载,就像C#一样。 You could export an function void Foo(int) and a function void Foo(double) . 您可以导出函数void Foo(int)和函数void Foo(double) Clearly those two functions could not both be exported as "Foo", the client of the DLL wouldn't know which one to pick. 显然,这两个功能不能都导出为“ Foo”,DLL的客户端不会知道选择哪个。 So it is not. 事实并非如此。

The C++ compiler solves that problem by decorating the name of the function. C ++编译器通过修饰函数名称来解决该问题。 Adding extra characters that makes a Foo(int) different from a Foo(double). 添加额外的字符,使Foo(int)与Foo(double)不同。 You can see those decorated names by running Dumpbin.exe /exports foo.dll from the Visual Studio Command Prompt, that lists the name of the exported functions. 您可以通过运行Visual Studio命令提示符中的Dumpbin.exe /exports foo.dll来查看这些修饰的名称,该命令列出了导出函数的名称。 Assuming your declaration was relevant, you'd see ?Foo@@YAXXZ . 假设您的声明是相关的,您会看到?Foo@@YAXXZ

So the corresponding declaration in your C# program should be: 因此,您的C#程序中的相应声明应为:

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

There are ways to change the C++ function declaration to make the C# declaration easier. 有多种方法可以更改C ++函数声明以使C#声明更容易。 Which is actually not a good idea, these decorated names actually help catch mistakes. 这实际上不是一个好主意,这些修饰的名称实际上有助于发现错误。

You should provide more information on your C++. 您应该提供有关C ++的更多信息。 Try using extern "C" __declspec(dllexport) instead. 尝试改用extern "C" __declspec(dllexport) C++ exports with strange names so using extern "C" avoids that. C ++导出的名称很奇怪,因此使用extern "C"可以避免这种情况。

If you didn't declare it extern "C" in your dll, its name has likely been "mangled". 如果您没有在dll中将其声明为extern“ C”,则其名称可能已被“缠住”。 You can use something like Dependency Walker to see what symbols your dll exports. 您可以使用Dependency Walker之类的工具查看dll导出的符号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM