C++加载动态链接库(cmake生成,隐式链接,显示链接)

C++程序在运行时有两种方式加载动态连接库:隐式链接显式链接
加载动态库文件就是将动态库中的代码逻辑映射到用户进程地址空间,就在程序执行的时候进行函数调用。

隐式链接

隐式链接是在程序开始执行时就将动态库文件加载到应用程序当中,需要在程序构建编译阶段就指定好,这种方式比较常用
unix的动态库只有.so文件,使用时需要配置工程:

  • 包含库头文件
  • 包含库.so文件地址
  • 链接库名称(多种方式)

windows的动态库包括.lib和.dll文件,其中.lib文件包含了导出函数的入口信息,.dll文件包含了导出函数的具体实现,使用时需要配置工程:

  • 包含库头文件
  • 包含库.lib文件地址
  • 链接库名称
  • 拷贝.dll文件到程序执行目录

关于通过cmake构建工程隐式链接动态库具体可参看cmake文档

显式链接

显式链接是程序在执行过程中可以随时加载、随时卸载动态库文件,所以显式链接比较灵活,适合用于热更新。

这里通过一个简单的demo来演示如何生成和使用,在动态连接库中显式链接导出的类。

生成

创建项目,生成动态库。
头文件中包含C++抽象类的接口和导出函数,将实际的派生类实现隐藏在动态库中,通过这种方式导出类。
如果只是需要导出C风格的函数,那么头文件中声明函数,实现部分隐藏在动态库中,在每个函数声明成导出即可。

项目结构

.
├── build
├── CMakeLists.txt
└── src
    ├── mytool.cpp
    └── mytool.h

CMakeLists.txt

cmake_minimum_required(VERSION 2.8)

# support c++11
add_definitions(-std=c++11)

project(mytool)

set(MYTOOL_SRC
    src/mytool.h
    src/mytool.cpp
)

# use SHARED mode as dynamic link
add_library(mytool SHARED ${MYTOOL_SRC})

# if this lib also depend on other lib, should add link here
#target_link_libraries(mytool 
#    # some lib name
#)

mytool.h

#ifndef _MYTOOL_H
#define _MYTOOL_H

// you can also use a namespace to wrap the code

class MyTool
{
public:
	virtual ~MyTool() {}; // shoud be virtual

	// interface functions
	virtual void fun1() = 0;
	virtual int fun2(int x, int y) = 0;
};

// export the implementation, will generate both .lib and .dll if in windows and .so for unix
#ifdef _WIN32
#define MYTOOL_EXPORT extern "C"  __declspec (dllexport)
#else
#define MYTOOL_EXPORT extern "C" 
#endif

MYTOOL_EXPORT MyTool *CreateMyTool();

#endif // !_MYTOOL_H

mytool.cpp

#include <stdio.h>
#include "mytool.h"

class MyToolExtend : public MyTool
{
public:
	MyToolExtend() {}
	virtual ~MyToolExtend() {}
	
	virtual void fun1() override;
	virtual int fun2(int x, int y) override;
};

void MyToolExtend::fun1()
{
	printf("real fun1 called\n");
}

int MyToolExtend::fun2(int x, int y)
{
	printf("real fun2 called\n");
	return x + y;
}

MyTool *CreateMyTool()
{
	return new MyToolExtend();
}

通过cmake编译
linux会生成libmytool.so
windows会生成mytool.libmytool.dll

使用

创建C++程序
main.cpp

#include <iostream>
#include "mytool.h" // include the lib header

// include shared lib load
#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h> # in linux, should also link to dl system library when build
#endif

// define shared lib load handler
typedef MyTool *(*CreateMyToolFunc)();

#ifdef _WIN32
HINSTANCE gDllHandler = nullptr;
const char *gDefaultSharedLibPath = "mytool.dll"; // here put it the same path
#else
void *gSoHandler = nullptr;
const char *gDefaultSharedLibPath = "libmytool.so"; // here put it the same path, some linux must use ./libmytool.so
#endif

int main()
{

#ifdef _WIN32
	// load shared lib
	gDllHandler = LoadLibrary(gDefaultSharedLibPath);
	if (!gDllHandler)
		std::cout << "load shared lib failed" << std::endl;

	CreateMyToolFunc create_mytool = (CreateMyToolFunc)(GetProcAddress(gDllHandler, "CreateMyTool"));
	MyTool *my_tool = create_mytool(); // get the derived class instance from shared lib

	my_tool->fun1();
	int z = my_tool->fun2(2, 3);
	printf("z: %d", z);

	// when all done, unload shared lib
	FreeLibrary(gDllHandler);
	gDllHandler = nullptr;
#else
	gSoHandler = dlopen(gDefaultSharedLibPath, RTLD_LAZY);
	if (!gSoHandler)
		std::cout << "load shared lib failed" << std::endl;

	CreateMyToolFunc create_mytool = (CreateMyToolFunc)(dlsym(gSoHandler, "CreateMyTool"));
	MyTool *my_tool = create_mytool(); // get the derived class instance from shared lib

	my_tool->fun1();
	int z = my_tool->fun2(2, 3);
	printf("z: %d", z);

	// when all done, unload shared lib
	dlclose(gSoHandler);
	gSoHandler = nullptr;
#endif

	return 0;
}

运行结果

real fun1 called
real fun2 called
z: 5

注意:

  • linux下使用需要链接系统dl
  • linux下指定so文件路径可能要./符号
  • windows下使用仅需要dll文件
  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值