当前环境:vs2015
1. 声明当前内容主要为记录在VS2015中编写dll和在项目中导入dll并执行函数的操作(从hotspot中发现dll可以通过LoadLibrary加载并执行)
加载和执行dll
- 隐式加载dll (#pragma comment(lib,“xx.lib”)方式加载)
- 显示加载dll(LoadLibrary方式加载)
1. 创建控制台项目并指定为dll程序
2.编写头文件test.h
#pragma once extern "C" _declspec(dllexport) void printStar(int rowNum,int cellNum);
这里需要注意的是:如果不使用extern "C" _declspec(dllexport) 表现所有的函数都是使用C++样式的,反之就是使用C样式的,C样式的不会修改函数名称,C++样式的会修改函数名称
这个对于后面的使用LoadLibrary方式加载dll和函数调用有非常重要的区别(LoadLibrary调用函数时按照函数名称得到函数指针的,如果得不到就会返回126)
这里为了解决LoadLibrary中的函数调用所以这里直接就保持不变(使用C导出样式)
3.编写函数实现
#include "stdafx.h" #include#include #include "test.h" void printStar(int rowNum, int cellNum) { for (int i = 0; i < rowNum; i++) { for (int j = 0; j < cellNum; j++) { printf("*"); } printf("n"); } }
开始生成dll和lib
首先将上面的test.h头文件拷贝到另外一个项目中,随后将TestDll.dll和Test.lib拷贝到项目的目录下面(必要时可以将test.h也拷贝进去)
1. 使用隐式调用方式
#include "stdafx.h" #include#include using namespace std; #include "test.h" #pragma comment(lib,"TestDll.lib") int main() { printStar(5, 5); getchar(); return 0; }
2. 使用显示调用方式
#include "stdafx.h" #include#include using namespace std; #include "test.h" int main() { void (*printStar)(int, int)=NULL; HINSTANCE handle; LPCWSTR libPath = TEXT("TestDll.dll");//; printf("before load dlln"); if ((handle = LoadLibrary(libPath))==0) { printf("dll load failed !n"); DWORD errorMsg = GetLastError(); std::cout << errorMsg << endl; return 0; } LPCSTR functionName = "printStar"; // 非C样式的函数导出会导致这个函数名称改变 printStar = (void (*)(int, int))GetProcAddress(handle, functionName); if (printStar==0) { printf("get function failed !n"); DWORD errorMsg= GetLastError(); std::cout << errorMsg << endl; return 0; } printStar(5,5); // 释放加载的lib FreeLibrary(handle); getchar(); return 0; }
执行结果都是一样的!
这里本人采用DLL Export Viewer查看dll
1. C样式的
2.C++样式的
这里可以发现C++样式的看不到函数名称,C样式的却可以看到
- 使用隐式导入的时候一般都是可以调用的,只要头文件正确,但是对于显示导入的时候就会出现C++和C的函数名称不一致的问题,导致显示导入出现找不到函数名称(默认vs采用C++的样式)
- 可以采用DLL Export Viewer观察生成的函数名称避免在导入中出现的各种问题
- 对于Linux中手动导入dll库的没有查看但是hotspot源码中已经有了加载dll的例子了



