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();
};
}
⑤ 再次查看接口
⑥ 调用同理(略)