C++动态链接库创建和使用

1. 动态链接库的基本概念

  • 动态链接库 (DLL):在运行时加载到内存中的共享库,可以在多个程序中复用,减少程序大小。
  • 静态库:在编译时直接链接到目标程序中,生成独立的可执行文件。

2. 创建动态链接库

2.1 动态库项目结构

假设动态MyDll,功能是提供一个add简单函数:

  1. 创建一个 项目命名 MyDll,新建bing.h和bing.cpp文件。(注意如果新建.h和.cpp文件和项目名称不一样,生成时不会生成.lib文件,需要在cpp文件里实现时候额外添加 extern "C" __declspec(dllexport)标注,如果我新建的为MyDll.h和MyDll.cpp文件就不会有这个问题,原因 不清楚)
  2. 使用 extern "C"__declspec(dllexport) 导出函数。
  3. 编译生成 MyDll.dll 和对应的 MyDll.lib

2.2 动态库代码

头文件 (bing.h):
#pragma once
//宏定义保护机制
#ifndef BING_H 
#define BING_H 
//C++ 编译器中编译时,会自动定义 __cplusplus 宏,"C"确保动态库的导出符号能被 C语言调用
#ifdef __cplusplus 
extern "C" {
#endif // __cplusplus

//新建动态库会自动定义MYDLL_EXPORTS 宏,定义MYDLL_API ,用于导出符号
#ifdef MYDLL_EXPORTS 
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif //!MYDLL_EXPORTS

MYDLL_API int add(int a, int b);      // 加法函数

#ifdef __cplusplus
}
#endif //1__cplusplus

#endif // !BING_H
源文件 (bing.cpp):
#include"bing.h"
#include"pch.h"

// 我的项目名和文件名不一致,额外标注extern "C" __declspec(dllexport)不然不会生成.lib文件
extern "C" __declspec(dllexport) int add(int a, int b) {
	return a + b;
}

3. 使用动态链接库

3.1 静态加载动态库

链接步骤
  1. 将动态库项目生成 MyDll.dllMyDll.lib、bing.h拷贝如执行目录
  2. 在主程序项目中,将 MyDll.lib 添加到链接器输入。(右键项目-》属性-》配置属性-》链接器-》输入-》附件依赖项-》添加xxx.Lib)。添加#include "bing.h"引用。
#include <iostream>
#include "bing.h"

int main() {
    int result = add(5, 3);
    std::cout << "Result: " << result << std::endl;
    return 0;
}

3.2 动态加载动态库

使用流程

  1. 将生成的MyDll.dll拷贝到执行目录下。

  2. 加载动态库:在运行时,使用系统 API 加载动态库,Windows 使用 LoadLibrary

  3. 获取函数地址

    • 通过 GetProcAddress(Windows)。
    • 将函数地址转换为函数指针进行调用。
  4. 释放动态库:使用 FreeLibrary(Windows)卸载动态库。

#include <iostream>
#include <Windows.h>
using namespace std;
typedef int (*AddFunction)(int, int); // 定义函数指针类型

int main() {
    // 加载动态库
    HMODULE hLib = LoadLibrary(TEXT("MyDll.dll"));
    if (!hLib) {
        cout << "Failed to load MyDll.dll" << endl;
        return -1;
    }

    // 获取 add 函数地址
    AddFunction add = (AddFunction)GetProcAddress(hLib, "add");
    if (!add) {
       cout << "Failed to get add function address" << endl;
        FreeLibrary(hLib);
        return -1;
    }

    // 调用函数
    int result = add(5, 3);
    cout << "Result: " << result << endl;

    // 释放动态库
    FreeLibrary(hLib);

    getchar();
    return 0;
}

对比总结

特性静态加载动态库动态加载动态库
加载时机程序启动时程序运行时
函数调用方式编译时解析符号,直接调用函数通过函数指针调用
依赖性程序启动时需确保 .dll 文件存在运行时可按需加载,无需启动时依赖
灵活性较低
性能较高略低,首次加载和解析符号有额外开销
适用场景静态加载更适合逻辑固定、对性能要求高的场景;动态加载则更适合需要高灵活性、按需加载功能模块的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值