如何使用minGW和SMVC两种方法编译.dll动态库和.lib静态库

MinGW编译器的全称是 Minimalist GNU for Windows。它提供了一个开发环境,使开发者可以在Windows上编写、编译和调试使用C、C++、Fortran等语言编写的程序,MinGW的核心是GCC编译器。
SMVC编译器的全称是 Simple Model-View-Controller,使用PHP框架,是Visual Studio软件中常用的编译方法。
一般使用minGW编译出的动态库和静态库格式分别为.dll和.dll.a;使用 SMVC 编译的动态库和静态库格式分别为.dll和.lib。两种格式的库文件不通用。

一、MinGW 编译

在CMakeLists文件中包含工程中用到的库文件,使用add_library命令编译出动态库,配置好该文件,其中Opencv的动态库地址已加入系统的环境变量中。

cmake_minimum_required(VERSION 3.5)

set(PROJECT_NAME PointLaserCalibration)
project(${PROJECT_NAME})

set(CMAKE_CXX_STANDARD 11)

set(OpenCV_DIR "D:/openCV/OpenCV-MinGW-Build-4.5.2/x64/mingw/lib")

find_package(OpenCV REQUIRED)

include_directories(
    include
    ${OpenCV_INCLUDE_DIRS}
    ${CMAKE_SOURCE_DIR}
)

set(SOURCES
    src/CPointLaserCalibration.cpp
)

add_library(${PROJECT_NAME} SHARED ${SOURCES})

target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})

target_compile_definitions(${PROJECT_NAME} PRIVATE MYLIBRARY_EXPORTS)

一般情况下,会使用下方的编译命令,这种方法编译出来的是.dll格式的动态库和.dll.a格式的静态库。

cmake -G "MinGW Makefiles" ..
cmake ..
cmake --build .

如果想要编译出.lib格式的静态库,需要在生成Makefile时将GNUtoMS打开,命令如下:

cmake -G “MinGW Makefiles” -DCMAKE_GNUtoMS:BOOL=ON ..
cmake ..
cmake --build .

至此,使用minGW编译出.dll和.lib。
注意:用此法编译出来的.dll和.lib,本人并没有在VS项目中成功使用,也就是说在本文下一部分中替换掉SMVC 编译出的.dll和.lib后,程序不能启动。问题待排查。

使用库文件

测试项目结构如下:
在这里插入图片描述

CMakeLists文件如下:

cmake_minimum_required(VERSION 3.5)

set(PROJECT_NAME TestPointLaserCalibration)
project(${PROJECT_NAME})

set(CMAKE_CXX_STANDARD 11)
set(OpenCV_DIR "D:/openCV/OpenCV-MinGW-Build-4.5.2/x64/mingw/lib")

find_package(OpenCV REQUIRED)

# 指定头文件目录
include_directories(${CMAKE_SOURCE_DIR}/dll)

# 指定库文件目录
link_directories(${CMAKE_SOURCE_DIR}/dll)

add_executable(${PROJECT_NAME} src/main.cpp)

target_link_libraries(${PROJECT_NAME} PointLaserCalibration)
target_link_libraries(${PROJECT_NAME} ${OpenCV_LIBS})

头文件 CPointLaserCalibration.h 如下:

#include<opencv2/opencv.hpp>

#define Smpclass_API ;
#ifdef Smpclass_API
#define Smpclass_API __declspec(dllexport)
#else
#define Smpclass_API __declspec(dllimport)
#endif

class Smpclass_API CPointLaserCalibration {
public:
    void calculateDtofPitch(const cv::Point3f& laser_point, float& pitch_angular);

    int getTestNum();
};

测试程序如下:实测输出无误

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

int main()
{
    std::cout << "Starting the program..." << std::endl;
    CPointLaserCalibration laserCalibration;
    float pitch_angular = 0.0;
    cv::Point3f laser_point(0.0, 0.0, 0.0);
    laserCalibration.calculateDtofPitch(laser_point, pitch_angular);
    int test_num = 1;
    test_num = laserCalibration.getTestNum();
    std::cout << "Pitch Angular: " << pitch_angular << std::endl;
    std::cout << "test_num: " << test_num << std::endl;
    return 0;

二、SMVC 编译

在VS中新建一个动态链接库(DLL)的项目。
在这里插入图片描述
把自己需要编译出动态库的代码导入进来,项目自动生成的pch.h和pch.cpp文件不用管,但也不能删除。
自己的头文件:

#include<iostream>
#include<opencv2/opencv.hpp>
#include<fstream>
#include<string>

#define Smpclass_API
#ifdef Smpclass_API
#define Smpclass_API __declspec(dllexport)
#else
#define Smpclass_API __declspec(dllimport)
#endif

class Smpclass_API CPointLaserCalibration
{
public:
    CPointLaserCalibration();

    struct TCameraParameter
    {
        cv::Mat camera_matrix;              // 内参矩阵
        cv::Mat rotat_matrix;               // 旋转矩阵
        cv::Mat trans_vector;               // 平移向量
    };
    
    void printTest();

    void getCameraParameter();

    void initLog();

private:
    cv::Rect                        m_out_rect;                // 四个黑色矩形的外接矩形
    cv::Point                       m_out_rect_center_pixel;   // 四个黑色矩形的外接矩形中心的像素坐标

    TCameraParameter                m_camera_para_100;
};

自己的cpp文件:
注意 #include “pch.h” 要放在最上面

#include "pch.h"
#include "CPointLaserCalibration.h"

CPointLaserCalibration::CPointLaserCalibration()
{
    getCameraParameter();
    initLog();
    printTest();
}

void CPointLaserCalibration::printTest()
{
    std::cout << "test success!!!" << std::endl;
}
// 截断

在项目的属性设置中,把项目本身的头文件和所用库的头文件都写入“包含目录”;把项目用到的所有静态库位置都写入“库目录”
在这里插入图片描述

把项目用到的静态库都加入到下图中的位置
在这里插入图片描述
右击项目,选择“生成”即可编译出.dll动态库和.lib静态库

使用库文件

在VS中新建一个空项目,同上面的操作一样,把头文件目录和库目录都包含起来,把自己的库文件和其他的库文件都链接到附加依赖项。按照原头文件中的函数声明方法调用自己的库文件,把所有用到的dll动态库文件和编译生成的exe文件单独放在一个文件夹中即可运行。
lib静态库文件只是在编译时用到,需要把函数声明编译到exe文件中,在运行exe文件时,只用到dll动态库文件。也就是说,在后续项目维护时需要改动库文件时,只需要替换最新的dll动态库文件即可。

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MSVC vs. MinGW 之 (lib,dll,def,obj,exe) vs (a,dll,def,o,exe) 玩转攻略手记 一份粗糙的研究记录,有待补完和整理。 MinGW: c -> o gcc -c a.c c -> exe gcc a.c libs.o -o a.exe (从主程序a.c,附加libs,生成a.exe) o -> exe gcc a.o b.o ... -o main.exe c -> dll,def,a gcc a.c -shared -o a.dll -Wl,--output-def,a.def,--out-implib,liba.a a -> dll a2dll liba.a dll -> a: dlltool --dllname a.dll --def a.def --output-lib liba.a (需要def文件) a -> def: dumpbin /exports lib.a > lib.def (在windows上调用,def需要修改) dll -> def : pexports a.dll -o > a.def (这里的-o是指给函数标序号) lib -> def : reimp -d a.lib lib -> a: (for __cdecl functions in most case) reimp a.lib; (for __stdcall functions) MSVC: c -> lib cl /LD a.c (注意已经定义了export列表) c -> dll cl /LD a.c c -> obj cl /c a.c c -> exe cl a.c /out:a.exe dll ->lib lib /machine:ix86 /def:a.def /out:a.lib (需要def文件) obj ->lib lib a.obj b.obj... /out:mylib.lib dll ->def DUMPBIN a.dll /EXPORTS /OUT:a.def (生成的def需要做修正) lib ->def reimp -d a.lib (这个要在MSYS+MinGW下用) 关于这些工具的适用范围可以很容易的理解和记忆。 dll和exe都是PE文件,所以可以使用pexports. lib和a是静态文件,都是归档类型,不是PE格式。所以不能使用pexports. dll可以使用dlltool. lib可以使用lib, 和reimp(lib->a工具) 所有的bin文件,包括dll,exe,lib,a都可以使用dumpbin. 参考: http://hi.baidu.com/kaien_space/blog/item/5e77fafa2ba9ff16a8d3110a.html Mingw官网文档: http://www.mingw.org/wiki/MSVC_and_MinGW_DLLs http://oldwiki.mingw.org/index.php/CreateImportLibraries http://www.mingw.org/wiki/FAQ http://hi.baidu.com/opaquefog/blog/item/9b21b6deb324e25dccbf1ab7.html http://qzone.qq.com/blog/8330936-1238659272 http://hi.baidu.com/jzinfo/blog/item/b0aa1d308de99f9da8018e00.html 本篇测试用代码: 1. main.cpp #include #include #include "mylib.h" using namespace std; int main() { char str[]="Hello world!"; printhello(str); return 0; } 2. mylib.cpp #include #include #include "mylib.h" using namespace std; void EXPORT printhello(char *str) { cout << str << endl; } 3. mylib.h #define EXPORT __declspec(

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值