1、创建DLL文件
(1) 创建一个工程CreateDll
(2) 刚创建的项目结构
(3) 在Header Files下添加一个头文件myDll.h
文件内容
//myDll.h #ifdef MYDLL_EXPORTS #define MYDLL_API __declspec(dllexport) #else #define MYDLL_API __declspec(dllimport) #endif namespace MyNameSpace{ class MyClass { public: static MYDLL_API void printHello(); static MYDLL_API double add(double number1, double number2); static MYDLL_API char* returnString(); }; }
(4) 在Source Files下添加一个cpp文件myDll.cpp
文件内容
//myDLL.cpp #include"stdafx.h" #include"myDll.h" #include<iostream> #include<stdio.h> using namespace std; namespace MyNameSpace{ double MyNameSpace::MyClass::add(double number1, double number2){ return number1 + number2; } void MyNameSpace::MyClass::printHello(){ std::cout << "Hello World" << std::endl; } char* MyNameSpace::MyClass::returnString(){ char* returnStr = "This is my string for return"; return returnStr; } }
(5) 添加完头文件和cpp文件后项目结构
(6) 点击编译或Ctrl+Shift+B
(7) 生成的Dll文件和Lib文件在Debug目录下
2、查看生成的CreateDll.dll提供的接口
(1) 查看命令
dumpbin.exe /EXPORTS D:\AAA_CODE\Test_Code\CallDll\Debug\CreateDll.dll
(2) dumpbin.exe路径
存放在VS2013安装目录下VC下的Bin里,例如:D:\VS2013\VC\bin\dumpbin.exe
(3) 运行命令,查看接口名称
(4) 接口名说明
由图可知,接口名称已经不是add,printHello和returnString了。这是由于采用了C++的编译方式,导致接口被重命名了。
2、使用DLL文件
(1) 静态调用
① 创建一个工程CallDll
② 添加myDll.h头文件目录 (添加工程的头文件目录:工程---属性---配置属性---c/c++---常规---附加包含目录:加上头文件存放目录。)
③ 添加CreateDll.lib目录(添加文件引用的lib静态库路径: 工程---属性---配置属性---链接器---常规---附加库目录:加上lib文件存放目录。)
④ 添加CreateDll.lib的lib名称( 添加工程引用的lib文件名:工程---属性---配置属性---链接器---输入---附加依赖项:加上lib文件名。)
⑤ 添加一个staticCall.cpp用于写调用代码
#include <iostream> #include "myDll.h" using namespace std; int main() { double a = 10.0; int b = 5.0; cout << "5.0 + 10.0 = " << MyNameSpace::MyClass::add(5.0, 1.0) << endl; //命名空间::类名::函数名 MyNameSpace::MyClass::printHello(); cout << "ret:" << MyNameSpace::MyClass::returnString() << endl; cin.get(); return 0; }
⑥ 添加DLL文件到Debug目录(没找到Debug目录时,可以先运行一下程序,就会自动生成)
⑦ 工程结构
⑧ 运行程序,查看结果。
(2) 动态调用
① 新建工程与静态调用一样。(这次直接用的同一个工程)
② 添加dynamicCall.cpp
//dynamicCall.cpp #include<iostream> #include<Windows.h> using namespace std; void addMode(){ typedef double(*add)(double number1, double number2); char* dllName = "CreateDll.dll"; HMODULE dllHandler = LoadLibrary(dllName); if (dllHandler != NULL){ //直接使用第一个函数(第二个,第三个同理) add testAdd = add(GetProcAddress(dllHandler, MAKEINTRESOURCE(1))); if (testAdd != NULL){ cout << "5.0 + 6.3 = " << testAdd(5.0, 6.3) << endl; } else{ cout << "Can not find function add" << endl; } } else { cout << "Load Library fail:" << dllName << endl; } } void printHelloMode(){ typedef void(*printHello)(); char* dllName = "CreateDll.dll"; HMODULE dllHandler = LoadLibrary(dllName); if (dllHandler != NULL){ //通过映射函数名来使用PrintHello函数(其他两个函数同理) printHello testPrintHello = printHello(GetProcAddress(dllHandler, "?printHello@MyClass@MyNameSpace@@SAXXZ")); if (testPrintHello != NULL){ testPrintHello(); } else{ cout << "Can not find function printHello" << endl; } } else { cout << "Load Library fail:" << dllName << endl; } } void returnStrMode(){ typedef char(*returnStr)(); char* dllName = "CreateDll.dll"; HMODULE dllHandler = LoadLibrary(dllName); if (dllHandler != NULL){ //两种方法实现returnStr returnStr testReturnStr = returnStr(GetProcAddress(dllHandler, "?returnString@MyClass@MyNameSpace@@SAPADXZ")); if (testReturnStr != NULL){ cout << "Mode by get function name:" << testReturnStr() << endl; } else{ cout << "Can not find function printHello" << endl; } returnStr testReturnStr2 = returnStr(GetProcAddress(dllHandler, MAKEINTRESOURCE(3))); if (testReturnStr2 != NULL){ cout << "Mode by get function index:" << testReturnStr2() << endl; } else{ cout << "Can not find function printHello" << endl; } } else { cout << "Load Library fail:" << dllName << endl; } } int main(){ addMode(); printHelloMode(); returnStrMode(); cin.get(); }
③ 添加DLL文件到Debug目录(没找到Debug目录时,可以先运行一下程序,就会自动生成)
④ 工程结构
⑤ 运行程序,查看结果。
3、Dll文件不改变函数名
① 添加CreateDll.def文件
//CreateDll.def LIBRARY CreateDll EXPORTS add = ?add@MyClass@MyNameSpace@@SANNN@Z printHello = ?printHello@MyClass@MyNameSpace@@SAXXZ returnString = ?returnString@MyClass@MyNameSpace@@SAPADXZ
② 重新编译后,再次查看接口名字
③ 用原来的函数名调用CreateDll.dll
//dynamicCall.cpp #include<iostream> #include<Windows.h> using namespace std; void addMode(){ typedef double(*add)(double number1, double number2); char* dllName = "CreateDll.dll"; HMODULE dllHandler = LoadLibrary(dllName); if (dllHandler != NULL){ //add testAdd = add(GetProcAddress(dllHandler, MAKEINTRESOURCE(1))); add testAdd = add(GetProcAddress(dllHandler, "add")); if (testAdd != NULL){ cout << "5.0 + 6.3 = " << testAdd(5.0, 6.3) << endl; } else{ cout << "Can not find function add" << endl; } } else { cout << "Load Library fail:" << dllName << endl; } } void printHelloMode(){ typedef void(*printHello)(); char* dllName = "CreateDll.dll"; HMODULE dllHandler = LoadLibrary(dllName); if (dllHandler != NULL){ //通过映射函数名来使用PrintHello函数(其他两个函数同理) printHello testPrintHello = printHello(GetProcAddress(dllHandler, "printHello")); if (testPrintHello != NULL){ testPrintHello(); } else{ cout << "Can not find function printHello" << endl; } } else { cout << "Load Library fail:" << dllName << endl; } } void returnStrMode(){ typedef char(*returnStr)(); char* dllName = "CreateDll.dll"; HMODULE dllHandler = LoadLibrary(dllName); if (dllHandler != NULL){ //两种方法实现returnStr returnStr testReturnStr = returnStr(GetProcAddress(dllHandler, "returnString")); if (testReturnStr != NULL){ cout << "Mode by get function name:" << testReturnStr() << endl; } else{ cout << "Can not find function returnString" << endl; } returnStr testReturnStr2 = returnStr(GetProcAddress(dllHandler, MAKEINTRESOURCE(3))); if (testReturnStr2 != NULL){ cout << "Mode by get function index:" << testReturnStr2() << endl; } else{ cout << "Can not find function returnString" << endl; } } else { cout << "Load Library fail:" << dllName << endl; } } int main(){ addMode(); printHelloMode(); returnStrMode(); cin.get(); }
④ 可以去除多余接口(由图可以看出接口翻倍了,但地址没变,现在清除函数名已被更改的接口,只要把myDll.h中__declspec(dllexport)去掉即可)
//myDll.h #ifdef MYDLL_EXPORTS #define MYDLL_API #else #define MYDLL_API #endif namespace MyNameSpace{ class MyClass { public: static MYDLL_API void printHello(); static MYDLL_API double add(double number1, double number2); static MYDLL_API char* returnString(); }; }
⑤ 再次查看接口
⑥ 调用同理(略)