【问题标题】:Regarding GetProcAddress关于 GetProcAddress
【发布时间】:2023-03-08 23:10:02
【问题描述】:

我有 MyDll.dll 及其函数定义如下

void pascal Myfunction(BOOL);

当我尝试在另一个项目中使用该函数时,我无法通过GetProcAddress() 获取该函数的地址。这是我的代码:

void callMyDll()
{
 HINSTANCE hDll;

 hDll=LoadLibrary(_T("MyDll.dll");

 if(hDll!=NULL)
 {
  cout<<"\n DLL Loaded \n";
 }
 else
  cout<<"\n DLL Not loaded\n"

 typedef void (__stdcall *MyFunction)(bool)

 Myfunction mf1 = (MyFunction) GetProcAddress(hDll, "MyFunction");

 if (mf1!=NULL)
  cout<<"\n Function Loaded Successfully \n";
 else
  cout<<"\n Function not loaded \n";

 FreeLibrary(hDll);
}

我得到的输出是:

DLL Loaded
Function not loaded

但是当我尝试使用像 glut32.dll 这样的已知 DLL 及其函数时,它工作正常。

我认为它的功能可能有问题

void pascal MyFunction(BOOL);

有人可以在这方面帮助我吗?

【问题讨论】:

  • 在头文件之后我已经包含了这个
  • 你记得导出函数吗?
  • 请向我们展示您的 DLL 源代码中的函数声明。

标签: c++ dll getprocaddress


【解决方案1】:

您需要使用extern "C" 来防止名称混淆并确保导出函数:

extern "C" __declspec(dllexport) void Myfunction(BOOL);

要查看 DLL 中的导出,您可以使用 Visual Studio 附带的 dumpbin.exe 实用程序:

dumpbin.exe /EXPORTS MyDll.dll

这将列出所有导出符号的名称。

除此之外,没有指定以下任一编译器开关:

Gz __stdcall calling convention: "Myfunction" would be exported as Myfunction@4
Gr __fastcall caling convention: "Myfunction" would be exported as @Myfunction@4

注意:我认为最后一个符号取决于编译器版本,但仍然不仅仅是“Myfunction”。

【讨论】:

  • 该函数被声明为pascal,这与x86上的__stdcall相同,因此无论编译器选项是什么,__declspec(dllexport)都会进行装饰。所以除非使用 .def 文件,否则它将是 _Myfunction@4
  • @DavidHeffernan,感谢您指出这一点。我在回答中省略了 pascal 调用约定,但也许这对 OP 来说是必要的。
【解决方案2】:

DLL 导出过程受名称修改和修饰的影响。长时间过时的 16 位 pascal 调用约定等效于 32 位平台上的 stdcall

首先您应该使用extern "C" 来指定C 链接并禁用名称修改。

但是,您的函数仍将受制于name decoration。如果您使用__declspec(dllexport) 导出它,那么它实际上将使用名称_Myfunction@4 导出。如果您希望以真实名称导出它,则需要使用 .def 文件。

但是,仍然有可能您根本没有从 DLL 导出函数。使用Dependency Walker 来检查它是否被导出,如果是,用什么名称导出。

【讨论】:

    【解决方案3】:

    您为什么使用pascal 呼叫约定?也许这会改变符号的名称,如果是这样,您可能需要考虑到这一点。

    【讨论】:

    • pascal 是一个 16 位调用约定,在 32 位上 #define'd 为 __stdcall
    【解决方案4】:

    符号将被装饰,所以它永远不会被称为MyFunction,它更可能是_MyFunction@4。您可以使用 dumpbin 之类的内容快速检查。

    您可以阅读更多关于重整here 的内容,如果您想避免重整,您需要使用def 文件来指定符号名称(或序数)。

    【讨论】:

    • 原始帖子中不清楚,但似乎extern "C" 正在使用中,这将防止函数名被破坏(前提是调用约定未被覆盖)但我已经要求导出的函数声明只是为了确定。
    • @AdamMaras:它仍然会在 Windows 上至少获得一个约定前缀(请参阅我的链接),extern "C" 只是说它必须是 C 风格的装饰,但他无论如何都在使用 C,它是多余的
    • 非常感谢,我可以加载函数了.. 太好了
    • @srinivasporam:如果它是正确的答案,您应该将其标记为正确答案(点击问题旁边的绿色勾号)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多