ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

使用msvc命令行编译静态库和动态库

2021-05-26 18:02:15  阅读:212  来源: 互联网

标签:命令行 lib int 编译 add jcdll cpp msvc 函数


因为最近园子在审核,先发在了CSDN。但我更喜欢博客园,现在搬运过来

编写一个静态库

编写要打包为静态库的函数,内容如下:

// jclib.cpp
int func(int a, int b)
{
    return a + b;
}

msvc开发人员命令提示符中执行

cl /c jclib.cpp

生成jclib.obj,这是编译产生的中间文件。然后使用lib工具将其打包为静态链接库*.lib文件。

lib jclib.obj

产生jclib.lib
写个头文件声明函数,供其他模块调用。

// jclib.h
int func(int,int);

接下来写个程序调用静态库中的func函数。

// 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;
}

编译链接测试例子

cl /EHsc demo.cpp

如果在demo.cpp中没有写#pragma comment语句,则执行如下编译命令

cl /EHsc demo.cpp jclib.lib

编写一个动态库

编写动态库中的函数

//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)表示函数要导出给其他模块使用
编写动态库头文件,声明函数,供其他模块调用

// jcdll.h
int __cdecl add(int,int);
int __cdecl subtract(int,int);

编译生成动态库

cl /LD jcdll.cpp

产生jcdll.dll,jcdll.lib,jcdll.exp
编写测试程序,调用jcdll中的函数

// 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);
}

编译测试程序

cl /EHsc demo.cpp

也可使用.def文件来定义要导出的函数

; jcdll.def
; this is comment
LIBRARY jcdll.dll
EXPORTS
	add		@1
	subtract	@2

EXPORTS字段可以这样写:

; 只导出函数名
func1 
; 导出函数名和序号
func2 @2 
; 只导出序号
func3 @3 noname  

编译动态库

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加载和卸载时将被调用。这里就不展开了,有兴趣可以查阅其他资料。

#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

// 加载动态库,如果动态库没有资源文件,只有代码,就没必要用LoadLibraryEx, 用LoadLibrary就行了,参数少
// 写在这里只是记下它的用法
// 需要包含<windows.h>

//HINSTANCE hDll = LoadLibrary(TEXT("jcdll.dll"));
HINSTANCE hDll = LoadLibraryEx(TEXT("jcdll.dll"), NULL, 0);
typedef int (*FUNCTYTE)(int, int); //函数指针
if (hDll != NULL)
{
	// 建议使用def文件定义导出函数,这样的话只要写"add"就可,不必搞这些
	//乱七八糟的函数名
    FUNCTYTE add = (FUNCTYTE)GetProcAddress(hDll, "?add@@YAHHH@Z");
    if (add)
        printf("add(1,2)=%d\n", add(1, 2));
    else
        printf("GetProcAddress() failed: %d\n",GetLastError());
}

FreeLibrary(hDll);

标签:命令行,lib,int,编译,add,jcdll,cpp,msvc,函数
来源: https://www.cnblogs.com/wangbingbing/p/14814492.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有