大肚婆敏姨,我行我速4.0,霸王龙vs棘背龙
dll(testcase_1.dll )源码:myfun.h
#pragma once #ifdef testcase_1_exports #define my_api __declspec(dllexport) #else #define my_api __declspec(dllimport) #endif #include <iostream> #include <string> namespace apicore { class my_api exportinterface { public: virtual void foo() = 0; }; extern "c" my_api exportinterface* getinstance(); #ifdef testcase_1_exports class exportclass :public exportinterface { private: std::string m_str; public: void foo(); }; #endif };
mufun.cpp
#include <iostream> #include "myfun.h" //#include "myfun2.h" using namespace std; namespace apicore { extern "c" my_api exportinterface* getinstance() { //apicore2::printinfo(); static exportclass ec; return &ec; } void exportclass::foo() { cout << "hi, i'm exportclass::foo" << endl; } }
可执行文件(alltest.exe)源码:
main.cpp
#include <iostream> //#include "..\\testcase_1\\myfun.h" //#pragma comment(lib, "..\\debug\\testcase_1.lib") #include <windows.h> #include "myfun.h" int main(int argc, char *argv[]) { //// 动态加载dll,不需要lib文件, //hinstance handle = getmodulehandle("testcase_1.dll"); // //if (handle == null) //{ // handle = loadlibrary("testcase_1.dll"); // typedef apicore::exportinterface* (*funtype)() ; // funtype fun = (funtype)getprocaddress(handle, "getinstance"); // if (fun) // { // fun()->foo(); // } // freelibrary(handle); //} // 静态加载调用,无法使用def文件,因为静态加载用的是lib文件 apicore::getinstance()->foo(); getchar(); return 0; }
如果都使用默认配置编译,只要设置好可执行文件的头文件包含目录(myfun.h所在目录),导入对应的lib(testcase_1.dll.lib)文件,然后把testcase_1.dll.dll放到alltest.exe同一目录。程序便可以正常运行。
那么def文件有什么用呢?
我们先改变一下testcase_1.dll的项目属性,调用约定由__cdecl改为__fastcall,可执行文件alltest.exe保持__cdecl调用约定不变
这个时候再次编译dll,生产成功
再重新编译生产可执行文件alltest.exe,编译失败,说找不到我们要使用的dll中的函数符号。
这是因为上面改了dll调用约定,而exe没有改。我们可以吧exe和dll的调用约定改成一样的,就没问题了。
这里我介绍另一种方法,就是使用我们的def文件。我们在testcase_1.dll这个项目中新添加一个def文件,
叫做sourc.def。内容如下
library "testcase_1.lib" exports getinstance
exports下的getinstance告诉编译器要导出的符号是getinstance,而是其他的,比如@getinstance@0,然后修改
项目属性如下:
再重新编译生产testcase_1.dll。这时候我们再次编译可执行文件,发现还是找不到符号,编译不通过。然后我们对可执行文件alltest.exe的代码做一点修改,
把dll加载有静态加载改为动态加载。修改main.cpp如下
#include <iostream> //#include "..\\testcase_1\\myfun.h" //#pragma comment(lib, "..\\debug\\testcase_1.lib") #include <windows.h> #include "myfun.h" int main(int argc, char *argv[]) { // 动态加载dll,不需要lib文件, hinstance handle = getmodulehandle("testcase_1.dll"); if (handle == null) { handle = loadlibrary("testcase_1.dll"); typedef apicore::exportinterface* (*funtype)() ; funtype fun = (funtype)getprocaddress(handle, "getinstance"); if (fun) { fun()->foo(); } freelibrary(handle); } //// 静态加载调用,无法使用def文件,因为静态加载用的是lib文件 //apicore::getinstance()->foo(); getchar(); return 0; }
然后重新编译运行,就可以了
def文件可以用于当dll的调用约定(__fastcall),与宿主(本例的alltest.exe)程序的调用约定不一致时(__cdecl),导致可执行文件在
使用dll时的链接出错。不过要注意的是,def文件从实验来看,只会影响dll中的输出符号,而不会影响lib中的输出符号。这也是为什么
我们不能再使用静态加载的方式,而要改为动态加载的方式。因为动态加载只使用dll,而静态加载链接时使用的是lib中的符号。
如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复
win10如何启用管理员账户 win10禁用/启用管理员账户的方法
win10怎么查看驱动是否异常 Win10检测驱动程序是否正常的方法
Windows10系统任务栏无效图标怎么删除 通过注册表一键快速删除
Win10系统自动重启怎么办 Win10系统自动重启的关闭方法
怎么减少win10笔记本功耗 详谈笔记本硬件功耗大的原因和解决办法
网友评论