Windows的静态库与动态库
Windows的静态库与动态库
1.静态库
1.1 静态库特点
- 运行不存在
- 静态库源码被链接到调用程序中
- 目标程序的归档
1.2 C语言静态库
- C静态库的创建
- 创建一个静态库项目。
- 添加库程序,源文件使用C文件。
int Clib_add(int add1,int add2){
return add1+add2;
}
int Clib_sub(int sub1,int sub2){
return sub1 - sub2;
}
- C静态库的使用
- 库路劲设置:可以使用pragma关键字设置
pragma comment(lib,"../lib/clib.lib")
#pragma comment(lib,"../Debug/Clib.lib")
#include <stdio.h>
#include <process.h>
int main(){
int sum,sub;
sum = Clib_add(5,3);
sub = Clib_sub(5,3);
printf("sum=%d,sub=%d\n",sum,sub);
system("pause");
return 0;
}
1.3 C++语言静态库
- C++静态库的创建
- 创建一个静态库项目
- 添加库程序,源文件使用cpp文件
int CPPlib_add(int add1,int add2){
return add1 + add2;
}
int CPPlib_sub(int sub1,int sub2){
return sub1 - sub2;
}
- C++静态库的使用
- 库路径设置:可以使用pragma关键字设置
pragma comment(lib,"../lib/cpplib.lib")
#include <iostream>
using namespace std;
//给链接器看
int CPPlib_add(int add1,int add2);
int CPPlib_sub(int sub1,int sub2);
//给编译器看
#pragma comment(lib,"../Debug/CPPlib.lib") //?CPPlib_add@@YAHHH@Z / ?CPPlib_sub@@YAHHH@Z
extern "C" int Clib_add(int add1,int add2);
extern "C" int Clib_sub(int sub1,int sub2);
#pragma comment(lib,"../Debug/Clib.lib") //Clib_add / Clib_sub
int main(){
//调c++库函数
int sum = CPPlib_add(5,4); //?CPPlib_add@@YAHHH@Z
int sub = CPPlib_sub(5,4); //?CPPlib_sub@@YAHHH@Z
cout << "sum=" << sum << ",sub=" << sub << endl;
//调c库函数
sum = Clib_add(5,3); //?Clib_add@@YAHHH@Z 使用extern "C",编译时不换函数名-->Clib_add
sub = Clib_sub(5,3); //?Clib_sub@@YAHHH@Z -->Clib_sub
cout << "sum=" << sum << ",sub=" << sub << endl;
system("pause");
return 0;
}
2.动态库
2.1 动态库特点
动态库的特点
- 运行时独立存在
- 源码不会链接到执行程序
- 使用时加载(使用动态库必须使动态库执行)
与静态库的比较
由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多分代码,所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过函数地址使用,所以代码体积小。
静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义(或地址)未变化,其他使用DLL的程序不需要重新链接。
2.2动态库创建
创建动态库项目
添加库程序
库程序导出 - 提供给使用者库中的函数等信息。
- 声明导出:使用_declspec(dllexport)导出函数
注意:动态库编译链接后,也会有LIB文件,是作为动态库函数映射使用,与静态库不完全相同。
制作动态库
_declspec(dllexport) int CPPdll_add(int add1,int add2){
return add1 + add2;
} _declspec(dllexport) int CPPdll_sub(int sub1,int sub2){
return sub1 - sub2;
} _declspec(dllexport) int CPPdll_mul(int mul1,int mul2){
return mul1 * mul2;
}
动态库原理图
- 模块定义文件:.def
例如:LIBRARY DLLFunc //库
EXPORTS //库导出表
DLL_Mul @1 //导出的函数
不加声明导出
int CPPdll_add(int add1,int add2){
return add1 + add2;
} int CPPdll_sub(int sub1,int sub2){
return sub1 - sub2;
} int CPPdll_mul(int mul1,int mul2){
return mul1 * mul2;
}
添加模块定义导出文件
LIBRARY CPPDll
EXPORTS
CPPdll_add @1
CPPdll_sub @2
CPPdll_mul @3
2.3动态库的使用
隐式链接(操作系统负责使动态库执行)
头文件和函数原型
可以在函数原型的声明前,增加_declspec(dllimport)
导入动态库的LIB文件
在程序中使用函数
隐式链接的情况,dll文件可以存放的路径:
- 与执行文件中同一个目录下(建议放在此目录下)
- 当前工作目录
- Windows目录
- Windows/System32目录
- Windows/System
- 环境变量PATH指定目录
#include <iostream>
using namespace std; _declspec(dllimport)int CPPdll_add(int add1,int add2);
_declspec(dllimport)int CPPdll_sub(int sub1,int sub2);
_declspec(dllimport)int CPPdll_mul(int mul1,int mul2);
//通知链接器到哪抓编号和dll文件名(CPPDll.dll)
#pragma comment(lib,"../Debug/CPPDll.lib") int main(){
int sum = CPPdll_add(5,4);
int sub = CPPdll_sub(5,4);
int mul = CPPdll_mul(5,4);
cout << "sum=" << sum << ",sub=" << sub << ",mul=" << mul << endl;
system("pause");
return 0;
}
显示链接(程序员自己负责使动态库执行)
定义函数指针类型 typedef
加载动态库
HMODULE LoadLibrary(
LPCTSTR lpFileName //动态库文件名或全路劲
); //返回DLL的实例句柄(HINSTANCE)
获取函数地址
FARPROC GetProcAddress(
HMODULE hModule //DLL句柄
LPCSTR lpProcName //函数名称
); //成功返回函数地址
使用函数
卸载动态库
BOOL FreeLibrary(
HMODULE hModule //DLL的实例句柄
);
#include <iostream>
#include <Windows.h>
using namespace std; typedef int(*FUNC)(int m,int n);
int main(){
HINSTANCE hDll = LoadLibrary("CPPDll.dll");
cout << "hDll:" << hDll << endl; FUNC add = (FUNC)GetProcAddress(hDll,"CPPdll_add");
cout << "addAdress:" << add << endl;
int sum = add(5,4);
cout << "sum:" << sum << endl; FUNC sub = (FUNC)GetProcAddress(hDll,"CPPdll_sub");
cout << "subAdress:" << sub << endl;
int su = sub(5,4);
cout << "sub:" << su << endl; FUNC mul = (FUNC)GetProcAddress(hDll,"CPPdll_mul");
cout << "mulAdress:" << mul << endl;
int mu = mul(5,4);
cout << "mul:" << mu << endl; system("pause");
FreeLibrary(hDll);
return 0;
}
2.4动态库中封装类
在类名称前增加_declspec(dllexport)定义,例如:
class _declspec(dllexport) CMath{
...
};
通常使用预编译开关切换类的导入导出定义,例如:
#ifdef DLLCLASS_EXPORTS
#define EXT_CLASS _declspec(dllexport) //dll
#else
#definE EXT_CLASS _declspec(dllimport) //使用者
#endif class EXT_CLASS CMath{
...
};
例子:
头文件
#ifndef _ClASSDLL_H
#define _CLASSDLL_H #ifdef DLLCLASS_EXPORTS
#define EXT_CLASS _declspec(dllexport) //dll
#else
#define EXT_CLASS _declspec(dllimport) //使用者
#endif class EXT_CLASS CMath{
public:
int add(int m,int n);
int sub(int m, int n);
}; #endif
源文件
#define DLLCLASS_EXPORTS
#include "ClassDll.h" int CMath::add(int m,int n){
return m + n;
} int CMath::sub(int m,int n){
return m - n;
}
调用动态库中的封装类
#include "..\ClassDll\ClassDll.h"
#include <iostream>
using namespace std;
#pragma comment(lib,"../Debug/ClassDll.lib") int main(){
CMath myMath;
int sum = myMath.add(5,4);
int sub = myMath.sub(5,4);
cout << "sum=" << sum << ",sub=" << sub << endl;
system("pause");
return 0;
}
Windows的静态库与动态库的更多相关文章
- Windows下静态库与动态库的创建与使用
Windows下静态库与动态库的创建与使用 学习内容:本博客介绍了Windows下使用Visual C++ 6.0制作与使用静态库与动态库的方法. --------CONTENTS-------- 一 ...
- Windows静态库和动态库的创建和使用
偶们在实际的编程开发中,经常会遇到运行时无法找到某个DLL文件或者链接时无法找到某个LIB文件.然后,我们就开始乱GOOGLE一下,然后将VS2005的设置改变一下,或许就Ok了,我们将别人开发的DL ...
- Windows下静态库、动态库的创建和调用过程
静态库和动态库的使用包括两个方面,1是使用已有的库(调用过程),2是编写一个库供别人使用(创建过程).这里不讲述过多的原理,只说明如何编写,以及不正确编写时会遇见的问题. //注:本文先从简单到复杂, ...
- C语言静态库与动态库(Windows下测试)
转载于:https://zhidao.baidu.com/question/1946953913764139388.html,原文为Linux上测试,本文为在Windows上编译测试 我们通常把一些公 ...
- Windows静态库和动态库的创建和使用(VS2005)
偶们在实际的编程开发中,经常会遇到运行时无法找到某个DLL文件或者链接时无法找到某个LIB文件.然后,我们就开始乱GOOGLE一下,然后将VS2005的设置改变一下,或许就Ok了,我们将别人开发的DL ...
- C++ 静态库与动态库以及在 Windows上 的创建、使用
一.什么是库 库是写好的现有的,成熟的,可以复用的代码.现实中每个程序都要依赖很多基础的底层库,不可能每个人的代码都从零开始,因此库的存在意义非同寻常. 本质上来说库是一种可执行代码的二进制形式,可以 ...
- 【C/C++开发】C++静态库与动态库以及在Linux和Windows上的创建使用
原文出处: 吴秦的博客 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学 ...
- C++ 系列:静态库与动态库
转载自http://www.cnblogs.com/skynet/p/3372855.html 这次分享的宗旨是——让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择 ...
- C++静态库与动态库
C++静态库与动态库 这次分享的宗旨是--让大家学会创建与使用静态库.动态库,知道静态库与动态库的区别,知道使用的时候如何选择.这里不深入介绍静态库.动态库的底层格式,内存布局等,有兴趣的同学,推荐一 ...
随机推荐
- burp-suite(Web安全测试工具)教程
Burp Suite 是用于攻击web 应用程序的集成平台.它包含了许多工具,并为这些工具设计了许多接口,以促进加快攻击应用程序的过程.所有的工具都共享一个能处理并显示HTTP 消息,持久性,认证,代 ...
- 二、jmeter模拟请求头及监听器之结果树
一.模拟请求头 利用jmeter发送http请求时,被接收的服务端会对发送的该请求进行初步判断,如果不是web端发送的请求就会被打回导致请求不通,这时候需要模拟请求头,模拟正常的用户行为进行发送请求 ...
- mybatis增删改返回的int是-2147482646,并不是想要返回结果
MyBatis发现更新和插入返回值一直为"-2147482646"的错误是由defaultExecutorType设置引起的,如果设置为batch,更新返回值就会丢失,返回结果就只 ...
- BD-rate的计算
相信不少接触视频编码的朋友在看相关的文献的时候,总会看到论文中测试时给出一个重要的参数BD-rate,可能一直心存疑问,这个BD-rate到底是个什么东西呢?可以参考这一份提案http://downl ...
- OCR-Form-Tools项目试玩记录(二)产品评测
这是一篇软工课程作业博客 项目 内容 这个作业属于哪个课程 北航2020春软件工程 006班(罗杰.任健 周五) 这个作业的要求在哪里 个人博客作业-软件案例分析 个人课程目标 系统地学习软件工程理论 ...
- docker 的常见命令行解析
1.查看本地镜像 sudo docker images 2.查看本地容器 sudo docker ps 3.根据Dockerfile制作镜像命令 sudo docker build -t Myimag ...
- [刷题] PTA 03-树2 List Leaves
程序: 1 #include <stdio.h> 2 #include <queue> 3 #define MaxTree 20 4 #define Null -1 5 usi ...
- 用户添加到sudoer列表## Allow root to run any commands anywhere root ALL=(ALL) ALL Iron ALL=(ALL) ALL
将用户添加到sudoer列表 李序锴关注 2017.12.20 15:03:25字数 605阅读 4,067 默认情况下,linux没有将当前用户列入到sudoer列表中(在redhat系列的linu ...
- ARM64平台编译stream、netperf出错解决办法 解决办法:指定编译平台为alpha [root@localhost netperf-2.6.0]# ./configure –build=alpha
ARM64平台编译stream.netperf出错解决办法 http://ilinuxkernel.com/?p=1738 stream编译出错信息: [root@localhost stream]# ...
- 032.Python魔术方法__new__和单态模式
一 __new__ 魔术方法 1.1 介绍 触发时机:实例化类生成对象的时候触发(触发时机在__init__之前) 功能:控制对象的创建过程 参数:至少一个cls接受当前的类,其他根据情况决定 返回值 ...