使用msvc命令行编译静态库和动态库
因为最近园子在审核,先发在了CSDN。但我更喜欢博客园,现在搬运过来
编写一个静态库
编写要打包为静态库的函数,内容如下: 1
2
3
4
5// jclib.cpp
int func(int a, int b)
{
return a + b;
}
在msvc开发人员命令提示符
中执行 1
cl /c jclib.cpp
生成jclib.obj
,这是编译产生的中间文件。然后使用lib
工具将其打包为静态链接库*.lib文件。
1
lib jclib.obj
产生jclib.lib
。
写个头文件声明函数,供其他模块调用。 1
2// jclib.h
int func(int,int);
接下来写个程序调用静态库中的func
函数。 1
2
3
4
5
6
7
8
9
10
11
12
13
14// demo.cpp
#include "jclib.h"
#include <stdio.h>
#pragma comment(lib,"./jclib.lib")//这里表明要链接的库,也可以在编译选项中指定
int main()
{
int a =1;
int b = 3;
int c = 3;
printf("c=%d\n",c);
c = func(a,b);//这个函数就在静态库中
printf("c=%d\n",c);
return 0;
}
编译链接测试例子 1
cl /EHsc demo.cpp
如果在demo.cpp
中没有写#pragma comment
语句,则执行如下编译命令
1
cl /EHsc demo.cpp jclib.lib
编写一个动态库
写法一
编写动态库中的函数 1
2
3
4
5
6
7//jcdll.cpp
__declspec(dllexport) int add(int a, int b){
return a + b;
}
__declspec(dllexport) int subtract(int a, int b){
return a - b;
}
__declspec(dllexport)
表示函数要导出给其他模块使用,如果代码里不写这个声明,那么就需要后边编译的时候用.def
文件来说明要导出哪些函数。(导出的意思是,有些函数在dll中是私有的,并不想被外界访问,那么就不导出这些函数)。
编写动态库头文件,声明函数,供其他模块调用 1
2
3// jcdll.h
int __cdecl add(int,int);
int __cdecl subtract(int,int);
编译生成动态库 1
cl /LD jcdll.cpp
产生jcdll.dll
,jcdll.lib
,jcdll.exp
编写测试程序,调用jcdll
中的函数 1
2
3
4
5
6
7
8
9
10
11// demo.cpp
#include "jcdll.h"
#include <stdio.h>
#pragma comment(lib,"./jcdll.lib")
int main()
{
int d = 1;
int e = 4;
int f = add(d,e);
printf("f=%d\n",f);
}
编译测试程序 1
cl /EHsc demo.cpp
写法二
这里仅说明和方法一操作不一样的地方
jcdll.cpp
中不写__declspec
在编译时使用.def文件来定义要导出的函数,分号开头是注释
1
2
3
4
5
6; jcdll.def
; this is comment
LIBRARY jcdll.dll
EXPORTS
add @1
subtract @2
EXPORTS字段可以这样写: 1
2
3
4
5
6; 只导出函数名
func1
; 导出函数名和序号
func2 @2
; 只导出序号
func3 @3 noname
编译动态库 1
cl /LD /DEF: jcdll.def jcdll.cpp
**注意:使用def文件定义导出函数和使用__declspec(dllexport)导出,产生的导出符号是不太一样的**,使用dumpbin /exports jcdll.dll
查看导出符号,发现前者导出符号和函数名完全一样,后者会被编译器打乱一点,变成?add@@YAHHH@Z
和?subtract@@YAHHH@Z
,对于隐式链接来说无妨,编译器会处理,对于显式链接,也就是用GetProcAddress
来获取函数指针时,要写?add@@YAHHH@Z
才能获取到函数指针。
另外,在dll中可以定义DllMain
来对dll加载和释放时进行操作。这个函数在加载dll加载和卸载时将被调用。这里就不展开了,有兴趣可以查阅其他资料。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#include <windows.h>
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
// https://blog.csdn.net/a7055117a/article/details/47733247
显式加载dll
1 |
|