再谈静态库和动态库(C++)

说明


  • 本文是在综合CSDN博客的基础上,再加上博主自己实践总结所写
  • 博主之前曾写过一篇博文介绍该内容,但那篇文章有囫囵吞枣之意,所以“再谈”
  • 本文若有错误之处,请在评论留言,及时回复
  • 本文涉及到的环境均为 Windows 10 + VS 2013

动态库和静态库联系与区别


  • 这是博主之前写的一篇入门文章,可以结合的看

VS下静态库与动态库的生成与使用

  • 其它相关文章,博主推荐

static lib和dynamic lib

VS2013动态库文件的创建及其使用详解

c++导出库

静态库(static lib)注意事项


  • 新建静态库工程

    • 正常写 .h 和 .cpp
  • 新建测试工程

    • 编辑 test.cpp
    • 将 .lib 复制到 test.cpp
    • 【属性 - 链接器 - 附加依赖项】加入 .lib 名称
    • 编译运行

动态库(dynamic lib + dll)注意事项


  • 新建动态库生成工程 DLLGenerater

    • 选择 控制台应用程序,其它请读者自行尝试,大同小异
    • 选择 DLL
    • 勾选 空项目
    • 预编译头VS 默认强制勾选
    • 安全开发生命周期(SDL)检查 选不选择无所谓
  • 新建若干 .h 和 .cpp,每个 .h 又可包括若干内容

    • math.h 和 math.cpp 示例代码(见文末所附代码)
    • animal.h 和 animal.cpp 示例代码(见文末所附代码)
  • 不写 main 函数

    • 如果想验证代码的正确性,可在属性默认类型配置类型像彗星修改为**.exe**进行编译运行
    • 编译即可,在 …/Debug 或者 …/Release 目录下生成 DLLGenerater.libDLLGenerater.dll
  • 新建测试动态库工程 DLLUser

    • 新建 test.cpp
    • 复制 math.h 和 animal.h 到 test.cpp 同一级目录
    • 复制 DLLGenerater.lib 和 DLLGenerater.dll 也到 test.cpp 同一级目录
    • DLLUser 属性的链接器的附加依赖项中添加 DLLGenerater.lib
    • 编辑 test.cpp 的内容(见文末所附代码)
    • 编译运行成功
  • 附:使用 DLLGenerater.dll 的几种方式

    • 编译运行时候

      • 第一种方式

        • .h、.lib、.dll、随 test.cpp 同一级目录
      • 第二种方式

        • .h、.lib 随 test.cpp 同一级目录
        • 系统环境变量的 system 的 path 加入 .dll 的路径(Windows 下可能需要重启电脑)
      • 第三种方式

        • .h 随 test.cpp 同一级目录
        • test.cpp 中加入 #pragma comment(lib,"DLLGenerater.lib")
        • 系统环境变量的 system 的 path 加入 .dll 的路径(Windows 下可能需要重启电脑)
      • 第四种方式(类似于配置第三方库)

        • 【项目属性 - VC++目录 - 包含路径】 添加 .h 路径
        • 【项目属性 - VC++目录 - 包含库目录】 添加 .lib 路径
        • 【项目属性 - 链接器 - 附加依赖项】 写入具体的 .lib 名称
        • 系统环境变量的 system 的 path 加入 .dll 的路径(Windows 下可能需要重启电脑)
    • 脱离VS运行时候

      • 第一种方式

        • 将 .dll 和 .exe 放在一起
      • 第二种方式(这个是我猜测的,未经实际验证

        • 预先就在文件中写入 .dll 的相对路径,这样的话可以在程序打包发布时候将 .dll 放入指定文件夹,具体可参见现有软件的安装程序(如参看 QQ 的安装程序路径)
  • 附:上述所提及代码

math.h

#ifndef _MATH_H_
#define _MATH_H_

#include <cmath> // 记得加头文件

// 有时候觉得写得麻烦
// 那么可以 typadef
#ifndef MY_DLL // 条件编译
#define MATH_EXPORT __declspec(dllexport)
#endif

// 对于函数(全局函数,成员函数等)
// __declspec(dllexport) 写在最前面
// 然后是返回值,函数名,形参
__declspec(dllexport) int add(int a, int b);

// 对于类,如果要导出所有函数
// 那么 __declspec(dllexport) 写在 class 和 类名中间
class __declspec(dllexport) ExportAllDll {
public:

    float getSin(float theta); // 普通成员函数
    static void printClass(); // 静态函数

private:

    const double PI = std::acos(-1);

    // 私有函数,不会导出!!!并且该导出无实际意义
    float __getTan(float theta);

};

// 对于类,如果要导出部分函数
// 则类名前不加 __declspec(dllexport)
// 而是在要导出的函数前面加上 __declspec(dllexport)
class ExportPartDll {
public:

    __declspec(dllexport) float getSqrt(float num); // 导出
    float getAbs(float num); // 不导出
};

// 也可以这样导出函数
MATH_EXPORT void getMatrix();

#endif // _MATH_H_

math.cpp

#include "math.h"
#include <iostream>

// .cpp 实现文件一概不写 __declspec(dllexport)
int add(int a, int b){
	return a + b;
}

// 类函数的实现记得加上类名
float ExportAllDll::getSin(float theta){
	return std::sinf(theta * PI / 180);
}

// 这里不写 static
void ExportAllDll::printClass(){
	std::cout << "printClass\n";
}

// 私有函数的实现
float __getTan(float theta){
	return 90.0f;
}

// 这个是要导出的函数
float ExportPartDll::getSqrt(float num){
	return std::sqrt(num);
}

// 这个不导出
float ExportPartDll::getAbs(float num){
	return std::abs(num);
}

// typedef __declspec(dllexport) MY_DLL 的使用
void getMatrix(){
	std::cout << "This is matrix.\n";
}

animal.h

#ifndef _ANIMAL_H_
#define _ANIMAL_H_

__declspec(dllexport) void printZoo();

#endif // _ANIMAL_H_

main.cpp

#include "animal.h"
#include <iostream>

void printZoo(){
	std::cout << "printZoo()\n";
}

test.cpp

#include "math.h"
#include "animal.h"
#include <iostream>

int main(){

	// 测试全局函数
	int a = 1, b = 2;
	std::cout << add(a, b) << std::endl;

	// 测试导出类
	ExportAllDll ad;
	std::cout << ad.getSin(30) <<std::endl;
	ExportAllDll::printClass();

	// 测试类导出函数
	ExportPartDll pd;
	std::cout << pd.getSqrt(9.0f) << std::endl;
	// std::cout << pd.getAbs(-6.6f) << std::endl;

	// 测试全局函数
	getMatrix();

	// 测试全局函数
	printZoo();

	return 0;
}

常见问题


C++ dll库只生成dll文件,而未生成lib文件的问题

Error LNK2001 无法解析的外部符号 的几种情况及解决办法

联系博主


评论会尽快回复

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值