尝试动态加载C++动态链接库,首先使用"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;
}请参考以上代码并指导我。
发布于 2017-01-04 10:14:35
这是因为名称是错误的(即函数的名称不是"run“,而是一些不同的东西)。
您的代码将用于(我测试的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;发布于 2017-01-04 10:10:31
实际上,DLL是在C时代引入的,从那时起,C++引入了函数名重载(取决于参数的类型),以及一些称为“错误名称”的东西,以允许以正确的名称链接函数调用。C++标准没有指定这个名称应该是什么样的。不同的编译器以不同的方式实现了参数的嵌入类型。
C++理解这个问题,有时需要有可预测的名称。在C++中有一个特殊的构造:
extern "C"
{
int run(int, int);
}当在GetProcAddress中指定函数的名称时,它应该与从DLL导出的函数完全相同。您可以使用像DependencyWalker这样的特殊实用程序来查看这些名称。
https://stackoverflow.com/questions/41461019
复制相似问题