【问题标题】:c++ unmanaged dll used by dllimport in C# produces entry point not found errorC# 中 dllimport 使用的 c++ 非托管 dll 产生未找到入口点错误
【发布时间】:2015-05-09 04:58:39
【问题描述】:

我知道这个问题已经在这里被问过很多次了。我已经阅读了所有可以找到的问题以及 stackoverflow 之外的信息。到目前为止,我还没有找到可以解决我遇到的具体问题的答案。

这里是非托管 c++ dll 头文件的代码。

namespace MyWin32DLL
{
    class MyWin32ClassOne
    {

    public:
        static __declspec(dllexport) int Getvar();

    };
}

这里是c++ dll cpp文件的代码

#include "MyWin32ClassOne.h"

namespace MyWin32DLL
{

    int MyWin32ClassOne::Getvar()
    {
        return 123;
    }
}

这段代码是我从各种来源汇总而成的,因此它可能根本不正确。我对 c++ 或 dll 不是很有经验。

这是我尝试访问 dll 的愚蠢的小 c# winforms prog 中的代码。 (已编辑以纠正 cmets 中 tolanj 指出的类型不匹配)

namespace TestDll
{
    public partial class Form1 : Form
    {

        [DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int Getvar();

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            string response = Getvar().ToString();

            MessageBox.Show(response, "title", MessageBoxButtons.OK);
        }
    }
}

现在,在这一点上,我明白我可能会收到“无入口点”错误,因为 c++ 编译器如何破坏方法和函数的名称。

根据我的阅读,我可以做两件事来解决这个问题。

事情 1 在我的声明之前添加 extern "c",这样名称就不会被编译器破坏。

namespace MyWin32DLL
{
    class MyWin32ClassOne
    {

    public:
        extern "C" static __declspec(dllexport) int Getvar();

    };
}

当我尝试此操作时,我从 Visual Studio 收到一条错误消息,指出“不允许链接规范”。

好的,所以我尝试第 2 件事,即使用 dumpbin 来查找我的函数的错位名称,并将错位名称用作 dllimport 调用中的入口点。

所以我在我的 dll 上运行了 dumpbin /symbols,但我没有得到函数名,无论是被损坏的还是其他的。

Dump of file mywin32cppdll.dll

File Type: DLL

  Summary

    1000 .data
    1000 .idata
    2000 .rdata
    1000 .reloc
    1000 .rsrc
    4000 .text
   10000 .textbss

接下来我试试 dumpbin /exports

Dump of file mywin32cppdll.dll

File Type: DLL

Section contains the following exports for MyWin32CppDll.dll

00000000 characteristics
554CF7D4 time date stamp Fri May 08 13:52:20 2015
    0.00 version
       1 ordinal base
       1 number of functions
       1 number of names

ordinal hint RVA      name

      1    0 00011005 ?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ = @ILT+0(?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ)

Summary

    1000 .data
    1000 .idata
    2000 .rdata
    1000 .reloc
    1000 .rsrc
    4000 .text
   10000 .textbss

看着我没有看到要使用的损坏或修饰的名称。但作为一个笨蛋,我使用“Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ”作为我的入口点,但在我的 c# 程序中仍然出现同样的错误。

显然我错过了一些东西。如何从我的 c# 程序中访问 dll 函数?

【问题讨论】:

  • Getvar 在你的 c++ 中输出 int 但你正在导入它说它输出一个字符串
  • 哎呀!是的,我尝试了很多不同的代码,试图找到一个有效的代码。进行更改时,我肯定存在类型不匹配。我已经修改了我的 c# 源代码以使用 int.更改变量类型后,原来的错误仍然存​​在。
  • 你能让你的函数不是类的一部分,而是一个过程吗?当 C++ 中的函数是类的一部分时,如果它访问类字段或函数可能会发生奇怪的事情,甚至使用一个编译器与另一个编译器编译的一个 C++ 类的 DLL 是有问题的,但在大多数编译器中单独使用是不可能的
  • @Mark Segal。在这种情况下,它不需要在一个类中。我想我正在使用一个类,因为那是我看到的一个例子。我将在没有课程的情况下尝试并报告。明天我才有机会这样做。

标签: visual-studio-2013 dllimport


【解决方案1】:

正如您所观察到的,该名称已被破坏。您已经设法在损坏名称的开头省略了?。您的导入应该是:

[DllImport("MyWin32CppDll.dll", CallingConvention = CallingConvention.Cdecl,
    EntryPoint = "?Getvar@MyWin32ClassOne@MyWin32DLL@@SAHXZ")]
public static extern int Getvar();

还请注意,您的函数使用 cdecl 调用约定。

【讨论】:

  • 我做了您推荐的更改,一切正常。谢谢你。我不敢相信我错过了“?”。这个答案解决了问题,但我也将接受 Mark Segal 的建议,并且 not 将所有内容都放在一个类中,因为它不需要。
猜你喜欢
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多