如何在通过LoadLibrary()加载的DLL内初始化c++类?



我的客户给我出了一个问题。

他们从他们的产品中删除了一些vc++项目,只有dll。

现在他们想用这些dll中的一些函数来处理一些数据。

假设这是dll中的一个类。

//MyClass.h
class __declspec(dllexport) MyClass{
public:
int a;
int b;
public:
MyClass();
int Sum(int, int);
}
//MyClass.cpp
MyClass::MyClass(){
a=0;
b=0;
}
int MyClass::Sum(int c, int d){
return c+d;
}

还有,这是exe.

//Test.exe
typedef void(__stdcall *TCon)();    // for constructor
typedef int(__stdcall *TSum)(int, int);    // for function Sum()
int main(){
HMODULE myDll = LoadLibrary(TEXT("MyClass.dll"));
FARPROC con = GetProcAddress(myDll, "??0MyClass@@QAE@XZ");  // I got this from DUMPBIN.exe
FARPROC sum = GetProcAddress(myDll, "?Sum@MyClass@@QAEHHH@Z");  // I got this from DUMPBIN.exe, too
TCon f_con = (TCon)con;
TSum f_sum = (TSum)sum;
f_con();    //Here I got access violation exception
printf("Sum is:%d¥n", f_sum(1,2));
return 0;
}

如果MyClass只有Sum()函数,没有构造函数,没有像a和b这样的成员,Sum()函数可以毫无问题地调用,我用VS2017测试了这个。

但是当类有构造函数和成员时,就会发生内存访问冲突。

我猜这可能是MyClass应该首先初始化,所以我试着调用构造函数,这就是为什么我添加了f_con,但f_con得到了相同的访问冲突问题。

客户要求的是,我们只有dll文件来导入类。

据我所知,有几种方法可以通过包含它们的头文件来从其他dll导入类。因为至少我们需要声明要导入的类。

我能做些什么来获得Sum()工作吗?

我觉得你错过了什么。没有必要在进入点上瞎折腾。除非你想把它当作练习。

当你的客户端代码也是c++时,你应该能够包括类的头文件,并像往常一样使用它。

然而(为了获得运行时链接)你必须能够在你的类声明的dllexport和dllimport之间切换。编译dll时必须使用Dllexport,使用dll时必须使用dllimport。

用COMPILING_DLL(命令行预处理器定义)编译你的dll然后用它添加一个头文件,并在你的类头文件中使用它。
#if COMPILING_DLL
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT __declspec(dllimport)
#endif

并将您的类声明更改为:

class DLLEXPORT  MyClass{...};

我找到我需要的了。

在我的测试中,使用内联汇编器语法将解决我的问题:
__asm {MOV ECX, p};  //p points to a malloc area for instance.

现在我可以将该类的INSTANCE关联到构造函数。

因为在EXE方面,我必须自己做所有事情,所以每次我想调用该类的函数时,我都需要使用汇编语法。这样的:

...
__asm {MOV ECX, p};  //move instance's address into the ECX register
f_con();  //call constructor
__asm {MOV ECX, p};  //move instance's address into the ECX register again
int r = f_Sum(1,2);  //call member function
...

现在我可以调用没有任何头文件的类成员函数了!

相关内容

最新更新