C++静态库和动态库的导入导出


一、静态库的导入和导出

1、导出静态库

(1)编写函数代码

double add(double x, double y) {
    return x + y;
}

(2)配置生成类型在这里插入图片描述
(3)生成解决方案,获得静态库.lib文件

2、导入静态库

(1)配置静态库的位置
在这里插入图片描述

(2)使用 extern 关键字声明已经定义的方法
方法一:使用#pragma comment(lib, “MyLib.lib”)链接静态库

#include <iostream>
//声明方法
extern double add(double x, double y);

//链接静态库
#pragma comment(lib, "MyLib.lib")

int main() {
    std::cout << add(1.0, 2.5);
    return 0;
}

方法二:手动配置
在这里插入图片描述

二、动态库的导入和导出(函数)

1.导出动态库(函数)

方法一:
(1)配置生成类型
在这里插入图片描述
(2)配置相关代码

//使用C语言形式导出,函数名不变
extern "C" __declspec(dllexport) int add(int a, int b) {
    return a + b;
}

//函数名变化
__declspec(dllexport) int add(int a, int b) {
    return a + b;
}

(2)生成动态库

方法二:
.h头文件

#pragma once

//如果没有定义,就是导出的,否则就是导入的宏
#ifndef DLL_IMPORT
#define API extern "C" __declspec(dllexport)
#else
#define API extern "C" __declspec(dllimport)
#endif

API int add(int a, int b);

.cpp

#include "mydll.h"
API int add(int a, int b) {
    return a + b;
}

2.导入动态库(函数)

方法一:通过链接静态库方法名,调用动态库的实现方法
(1)导入库目录
在这里插入图片描述
(2)配置相关代码

对应导出方法一:

//把dllexport变为dllimport
extern "C" __declspec(dllimport) int add(int a, int b);

//链接库, 此种方法不仅需要静态库还需要把动态库拷贝至编译目录下
#pragma comment(lib, "MyDll.lib")
int main() {
    std::cout << add(1, 2);
}

对应导出方法二:

#define DLL_IMPORT
#include "../MyDll/mydll.h"

#pragma comment(lib,"MyDll.lib")

int main() {
    std::cout << add(1, 2);
}

(3)把动态库.dll拷贝至目录下

方法二:调用Windows的API调用动态库

//第二种方法
//使用windows的API,来将动态库加载到内存里。
#include <iostream>
#include <Windows.h>
int main() {
    //std::cout << add(1, 2);

    //加载动态库至内存中
    HINSTANCE hDll = LoadLibrary(L"MyDll.dll");
    if (hDll == nullptr) {
        std::cout << "Load dll failed!";
        return -1;
    }

    //创建函数指针
    using functionPtr = int(*)(int, int);

    //找到所需要的函数
    functionPtr addFunction = (functionPtr)GetProcAddress(hDll,"add");

    if (addFunction == nullptr) {
        std::cout << "cannot find target function!";
        return -1;
    }
    //使用函数
    std::cout << addFunction(1, 2);
}

三、动态库的导入和导出(类)

可以使用函数,返回一个实例对象的方式

1.导出动态库(类)

方法类似动态库的导出(函数),但是应为C语言中没有类的概念,所以代码中的宏定义不需通过C语言。
.h头文件

    #pragma once

    #ifndef DLL_IMPORT
    #define API __declspec(dllexport)
    #else
    #define API __declspec(dllimport)
    #endif // !DLL_IMPORT
#include <string>
class API InterfaceClass {
public:
    int result;
    //不建议在动态库中,直接导出C++基础数据类型数据.
    //对于标准库,标准模板库中,不同版本的库有着不同的实现,msvc有着不同的实现,可能会发生更改,则会出现问题.
    //因此推荐导出的都是C++的基础数据类型,即不需要引用的头文件的数据类型.
    //这也是在基类中,使用纯虚函数的原因.
    //std::string str;
    virtual int add(int a, int b) = 0;
};

class ExportedClass :public InterfaceClass {
public:
    virtual int add(int a, int b) override;
private:
    std::string str;
};

extern "C" API InterfaceClass * getInstance();

//1、创建一个基类,导出一些使用的变量、函数,函数设为纯虚函数
//2、导出想要的类,并且继承该基类
//3、实现上面的纯虚函数,可以使用一些C++的类型,但需要设置为私有
//4、需要一个函数,返回一个指向基类的指针,通过函数的方式返回指针。

.cpp文件

#include "mydll.h"

int ExportedClass::add(int a, int b) {
    return a + b;
}

InterfaceClass* getInstance() {
    InterfaceClass* ptr = new ExportedClass();
    return ptr;
}

2.导入动态库(类)

把生成的动态库.dll拷贝到运行环境下。
方法一:

#include "../ExportClassDll/ExportClassDll/mydll.h"
#include <iostream>
//导出类的时候,需要连接静态库,还需要把动态库拷贝到文件中
#pragma comment(lib,"ExportClassDll.lib")
#include <Windows.h>
int main() {
    ExportedClass instance;
    std::cout << instance.add(1, 2);
    return 0;
}

方法二:

int main() {
    InterfaceClass* ptr = getInstance();
    std::cout<<ptr->add(1, 2);
}

方法三:

int main() {
    HINSTANCE hDll = LoadLibrary(L"ExportClassDll.dll");

    //函数指针
    using funPtr = InterfaceClass * (*)();

    funPtr getInstancePtr = (funPtr)GetProcAddress(hDll, "getInstance");

    InterfaceClass* ptr = getInstancePtr();
    std::cout<<ptr->add(1, 2);
}

总结

动态库和静态库的lib文件具有不同的功能,动态库的lib文件只具备类似声明的功能,不具备实现内容。
使用动态库导出类的步骤:
1、创建一个基类,其中包括需要的变量、函数(纯虚函数)。
2、要导出的类,继承自基类。
3、一个返回基类指针的函数,动过多态,返回导出类。
导入步骤:
1、加载动态库。
2、通过函数指针得到这个函数。
3、调用得到需要的类。

  • 10
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值