GetProcAddress函数返回NULL

时间:2017-01-04 10:01:59

标签: c++ windows dll getprocaddress

我尝试动态加载C ++ dll,首先我使用" LoadLibrary"加载了dll。功能,它正确处理它。之后我尝试使用" GetProcAddress"来获取DLL文件函数的函数指针,它返回NULL。请找到我的DLL代码并测试应用程序代码,并告诉我代码中出错的地方。

dummy2.h

namespace newer
{
  class dllclass
  {
    public:
        static __declspec(dllexport) int run(int a,int b);
  };
}

dummy2.cpp

#include <iostream>
using namespace std;

#include "dummy2.h"

namespace newer
{
  int dllclass::run(int a,int b)
  {
    return a+b;
  }
}

dummy1.cpp

#include "stdafx.h" 
#include <windows.h>

#include <iostream>
using namespace std;
typedef int (*Addition)(int,int);

int _tmain(int argc, _TCHAR* argv[])
{
  Addition add;
  HINSTANCE hDLL;
  hDLL = LoadLibrary(TEXT("Dummy2.dll"));

  add = (Addition)GetProcAddress(hDLL, "run");  

  getchar();
  return 0;
}

请参考上面的代码并指导我。

2 个答案:

答案 0 :(得分:5)

这是因为名称被破坏了(即函数的名称不是“运行”但是有些不同)。

您的代码可以使用(对于我测试过的MSVC 2013):

add = (Addition)GetProcAddress(hDLL, "?run@dllclass@newer@@SAHHH@Z");
cout << add(1, 2) << endl;

一般情况下,如果您想通过插件加载课程,最好的方法是使用虚拟界面。一个例子:

//dummy2.h
namespace newer
{
  class dllclass_interface
  {
    public:
        virtual int run(int a,int b) = 0;
 };

}

extern "C" __declspec(dllexport) newer::dllclass_interface* getDllClass();
//dummy2.cpp
#include <iostream>
using namespace std;

#include "dummy2.h"

namespace newer
{
  class dllclass: public dllclass_interface
  {
    public:
        virtual int run(int a,int b);
 };

  int dllclass::run(int a,int b)
  {
    return a+b;
  }
}

extern "C" newer::dllclass_interface* getDllClass()
{
    static newer::dllclass instance;
    return &instance;
}
typedef newer::dllclass_interface* (*GetClassFunc)();

GetClassFunc getClassFunc = (GetClassFunc)GetProcAddress(hDLL, "getDllClass");

newer::dllclass_interface* dllClass = getClassFunc();
cout << dllClass->run(a, b) << endl;

答案 1 :(得分:1)

事实上,DLL是在C时代引入的。从那以后,C ++引入了函数名称重载(取决于参数的类型)和称为“受损名称”的东西,以允许将函数调用与正确的名称链接。 C ++标准没有指定此名称的外观。不同的编译器实现了以不同方式将参数类型嵌入到名称中。

C ++理解这个问题,有时需要有可预测的名称。 C ++中有特殊的构造:

extern "C"
{
     int run(int, int);
}

GetProcAddress中指定函数的名称时,它应该与从DLL导出的名称完全相同。您可以使用DependencyWalker等特殊实用程序查看这些名称。