IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> Windows+MinGW使用CMake生成.dll动态链接库 -> 正文阅读

[开发工具]Windows+MinGW使用CMake生成.dll动态链接库

Windows+MinGW使用CMake生成.dll动态链接库

序言

在完成接口开发后,为了给其他开发人员调用,通常需要将这部分代码打包生成动态链接库文件。

动态链接库很好地保证了代码的封装性和独立性,作为接口,它可以很好地独立于主程序,便于更新。调用接口的主程序编译时也会绕过已生成的动态链接库,仅作连接,在运行时使用它,减少了前端人员编译的时间消耗。

同时由于动态链接库很难被反编译,只有头文件是可见的,这也同时保证了代码的安全性。

在Windows系统上,以.dll为后缀的是动态链接库,以.a结尾的是静态链接库。

静态连接库就是把(lib)文件中用到的函数代码直接链接进目标程序,程序运行的时候不再需要其它的库文件;动态链接就是把调用的函数所在文件模块(DLL)和调用函数在文件中的位置等信息链接进目标程序,程序运行的时候再从DLL中寻找相应函数代码,因此需要相应DLL文件的支持。

*Linux系统上的动态链接库后缀为.so,静态链接库后缀还是.a。本篇不做过多介绍。

环境概览

  • 操作系统:Windows 10
  • 编译器:MinGW-w64

目录结构

│  CMakeLists.txt
│
├─build
│
├─examples
│      test_api.cpp
│          
├─include
│  └─detectionapi
│          DetectionApi.h
│          
├─lib
│      libopencv_calib3d450.dll
│      libopencv_core450.dll
│      
└─src
       DetectionApi.cpp

编写CMakeLists.txt

首先,为保证目录结构的干净,先将待编译的文件整理为上述目录结构。
上述目录中,include存放头文件(.h, .hpp),src存放源文件(.c, .cpp),examples存放测试代码,lib存放各种支持程序运行的链接库。CMakeLists.txt放在根目录下,将编译生成的内容全部放在build目录下。

然后开始编辑CMakeLists.txt文件,一个样例如下所示。

# 最低CMake版本要求
cmake_minimum_required(VERSION 3.9.0)

# 项目名称,编译好dll或exe的名称
project(detection)

# 设置C/C++标准
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 头文件路径
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include/detectionapi)
include_directories(../opencv/build/include)
include_directories(../opencv/build/include/opencv2)

# 枚举头文件
file(GLOB_RECURSE INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/include/detectionapi/*.h)

# 指定引用的外部库的搜索路径
LINK_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lib)

# 枚举源文件
file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

# 输出路径
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

# 链接
set(LINK_LIBS
    libopencv_calib3d450.dll
    libopencv_core450.dll
)

# 生成dll库
ADD_LIBRARY(detectionapi SHARED ${INCLUDES} ${SOURCES})
TARGET_LINK_LIBRARIES(detectionapi ${LINK_LIBS})
INSTALL(TARGETS detectionapi DESTINATION  ${CMAKE_CURRENT_SOURCE_DIR}/lib)

# 设置目标属性
SET_TARGET_PROPERTIES(detectionapi PROPERTIES LINKER_LANGUAGE C
        ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
        LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
        RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
        OUTPUT_NAME "DetectionApi"
        PREFIX "")

# 生成可执行文件,仅用作测试
add_executable(detection examples/test_api.cpp ${INCLUDES})
TARGET_LINK_LIBRARIES(detection ${LINK_LIBS})
TARGET_LINK_LIBRARIES(detection ${PROJECT_BINARY_DIR}/lib/libDetectionApi.dll.a)

如上述样例所示,一个标准的CMake文件包含了以下几大部分:

  • 基础配置:完成一些CMake所需的基础配置,包括了版本要求,项目名称,C++标准等。
  • 输入配置:所有需要的头文件,源文件,外部链接库。
  • 输出配置:生成内容,生成属性等。包括了输出路径,输出类别(可执行程序,dll库等)。

上述示例,基础配置和输入配置是比较显而易见的,这里着重说一下输出配置。

ADD_LIBRARY(detectionapi SHARED ${INCLUDES} ${SOURCES})
声明这是一个lib库,第一个参数是链接库属性,第二个是类型(SHARED表示动态链接库),第三个参数是输入参数中的头文件和源文件。

TARGET_LINK_LIBRARIES(detectionapi ${LINK_LIBS})
这个是链接的第三方库,如自行编译出的opencv的各种dll等。

INSTALL(TARGETS detectionapi DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/lib)
dll的实际安装指令,按照上述写法将被安装在/lib目录下。

SET_TARGET_PROPERTIES(detectionapi PROPERTIES LINKER_LANGUAGE C
        ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
        LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
        RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
        OUTPUT_NAME "DetectionApi"
        PREFIX "")

设置dll属性的实际内容。

  • PROPERTIES LINKER_LANGUAGE C:声明为C链接库,提高DLL库的兼容性。
  • OUTPUT_NAME:DLL库输出名称。
  • PREFIX:DLL库前缀,若不设置,可能会加默认前缀。

add_executable(detection examples/test_api.cpp ${INCLUDES})
生成可执行程序,这里是利用examples/test_api.cpp来测试封装的dll是否生效。程序主要就是引用了DetectionApi.h,调用给出的函数,观察是否有打印信息。可执行程序仅用作测试dll,没有实际意义,CMake文件可以不包含这段代码。

TARGET_LINK_LIBRARIES(detection ${PROJECT_BINARY_DIR}/lib/libDetectionApi.dll.a)
为了测试dll,就不包含cpp,而是使用静态链接库替代cpp进行编译(原来exe的生成方式是.h + .cpp,现在是.h + .dll.a)。这样,可执行程序在运行时就会去同级目录下找你的dll文件了。而dll.a在此之后也就没有用了。

需要注意的是,本文操作全过程不需要修改原始代码,CMake过程是独立于代码之外的。

CMake语法内容非常庞大,在实际使用中,要多查阅CMake官方文档。
CMake Documentation

编译

可以在build/目录下通过cmake ..命令,或者通过CMake-GUI编译到build/目录下。
然后在build/下通过make命令执行生成的Makefile脚本,生成可执行程序和.dll文件。
最后通过make install在指定位置/lib生成.dll文件。

完成后新的目录结构为:

│  CMakeLists.txt
│
├─build
│  ├─bin
│  │       detection.exe
│  ├─CMakeFiles
│  ├─lib
│  │       detectionapi.dll
│  │       libdetectionapi.dll.a
│  └─Makefile
│
├─examples
│      test_api.cpp
│          
├─include
│  └─detectionapi
│          DetectionApi.h
│          
├─lib
│      detectionapi.dll
│      libdetectionapi.dll.a
│      libopencv_calib3d450.dll
│      libopencv_core450.dll
│      
└─src
       DetectionApi.cpp

测试

生成的可执行程序位于build/bin下,将所有需要的第三方dll库放在同级目录下,并将DetectionApi.dll也放于此。双击.exe,成功运行。
完成dll封装,给其他开发人员调用时,就只需要提供.h和.dll了,非常的方便。

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2022-06-25 18:20:21  更:2022-06-25 18:20:38 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/14 15:07:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码