• Windows环境C++工程的动态库导出与调用


            算法工程师经常与前端对接,一般地,我们不会将源码打包直接发给对方,而是将函数方法编译成库(即:win下的DLL or LIB文件)

    一方面是为了保密,另一方面是为方便使用(假如你的算法几十个cpp,别人连带界面cpp编译很费时间)。常用的库打包有如下三个方式,本文采用第一种方式作为范例。

    三种方式区别:

    1、采用第一种方法时,需要包含文件:.h .lib .dll,有头文件,具有可读性; 

    2、第二种和第三种库使用时,需要预编译、预加载等操作,第三种直接连头文件都看不到,

    保密性最好,这里不作多讨论。

       下文采用第一种导出方式,即:动态链接库(DLL),导出文件有:.h .lib .dll

     

    一、创建导出库工程

    打开VS2019, 点击:文件 -> 新建 -> 项目->动态连接库(DLL),选中如上图第一项,新建工程;自动生成如下几个文件,我们全部删除。

    项目属性-C/C++-预编译头默认如下图设置

     

    将其修改为如下内容: 

     最后,别忘记设置工程为Release X64,

    二、编写库导出.h .cpp文件

         所谓编写库导出文件,也就是编写代码,告诉编译器,那些函数、类、变量要导出到库文件中。这里给出一个范例,以后用照抄就行(该工程不需要

    执行,所以没有main函数);

    下面的声明的集合函数,可以改为任何自定义函数,记得:函数和类前面加宏定义:API_SYMBOL(也即:__declspec(dllexport))

    ,下面MyDll.cpp文件记得要加 #define BUILD_MYDLL

    注意:这里给出了C风格函数、C++模板函数、全局变量、类的导出方式,经过多个工程测试,方法有效。

    MyDll.h

     1 #pragma once
     2 
     3 #ifdef BUILD_MYDLL
     4 #define API_SYMBOL __declspec(dllexport)
     5 #else
     6 #define API_SYMBOL __declspec(dllimport)
     7 #endif // BUILD_MYDLL
     8 
     9 // OS
    10 #include<iostream>
    11 // ThirdParty
    12 #include<opencv2/opencv.hpp>
    13 #include<Eigen/Core>
    14 
    15 // 导出全局变量
    16 extern "C" API_SYMBOL int globa_a;
    17 
    18 // 导出函数
    19 extern "C" API_SYMBOL int FunAdd(int a, int b);
    20 
    21 extern "C" API_SYMBOL cv::Mat FunMatAdd(const cv::Mat& m1, const cv::Mat& m2);
    22 
    23 // 导出C++模板函数
    24 API_SYMBOL Eigen::Matrix2d FunMatAdd(const Eigen::Matrix2d& m1, const Eigen::Matrix2d& m2);
    25 
    26 //导出类
    27 class API_SYMBOL MyClass
    28 {
    29 public:
    30     MyClass();
    31     ~MyClass();
    32 
    33 private:
    34 
    35 };

    MyDll.cpp

     1 #define BUILD_MYDLL // 由于是导出函数,所以徐娅哦定义.h文件中的BUILD_MYDLL
     2 #include "MyDll2.h"
     3 
     4 int globa_a = 999;
     5 
     6 // 删除宏API_SYMBOL
     7 int FunAdd(int a, int b)
     8 {
     9     std::cout << "globa_a = " << ++globa_a << std::endl;
    10     return a + b;
    11 }
    12 
    13 cv::Mat FunMatAdd(const cv::Mat & m1, const cv::Mat & m2)
    14 {
    15     std::cout << "globa_a = " << ++globa_a << std::endl;
    16     return m1 + m2;
    17 }
    18 
    19 Eigen::Matrix2d FunMatAdd(const Eigen::Matrix2d & m1, const Eigen::Matrix2d & m2)
    20 {
    21     std::cout << "globa_a = " << ++globa_a << std::endl;
    22     return m1 + m2;
    23 }
    24 
    25 MyClass::MyClass()
    26 {
    27     std::cout << "MyClass" << std::endl;
    28 }
    29 
    30 MyClass::~MyClass()
    31 {
    32 }
    View Code

    直接编译,可以看到如下信息:

    1 1>  正在创建库 D:VS2017_ProjectCameraProjectorCalibrationx64ReleaseMyDll.lib 和对象 D:VS2017_ProjectCameraProjectorCalibrationx64ReleaseMyDll.exp
    2 1>正在生成代码
    3 1>All 939 functions were compiled because no usable IPDB/IOBJ from previous compilation was found.
    4 1>已完成代码的生成
    5 1>ExportDLL.vcxproj -> D:VS2017_ProjectCameraProjectorCalibrationx64ReleaseMyDll.dll
    6 1>已完成生成项目“ExportDLL.vcxproj”的操作。
    7 ========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========

    三、库打包与测试

           现在将上述MyDll.h、MyDll.lib、MyDll.dll三个文件放到一起,我们新建一个控制台工程测试这些库,注意:上述编译库的时候,我使用了第三方库,如:Eigen等,

    在测试工程中,也需要将这些库提前包含进来。

            新建好测试工程后,我们引入上面三个文件,这和配置OpenCV没什么区别,不多说。

    测试文件,test.cpp

     1 // DemoInvokeDll2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
     2 //
     3 
     4 #include <iostream>
     5 #include<MyDll.h>
     6 
     7 int main()
     8 {
     9     globa_a = 66;
    10 
    11     cv::Mat m1 = (cv::Mat_<uchar>(3, 1) << 1, 2, 3);
    12     cv::Mat m2 = (cv::Mat_<uchar>(3, 1) << 1, 9, 2);
    13     cv::Mat m3 = FunMatAdd(m1, m2);
    14 
    15     Eigen::Matrix2d m4, m5, m6;
    16     m4 << 1, 2, 3, 4;
    17     m5 << 2, 3, 4, 5;
    18     m6 = FunMatAdd(m4, m5);
    19     std::cout << m6(0, 0) << ", " << m6(0, 1) << std::endl;
    20     std::cout << m6(1, 0) << ", " << m6(1, 1) << std::endl;
    21 
    22     MyClass mc;
    23     return 1;
    24 }

    注意全局变量等,成功调用!

    CV&DL
  • 相关阅读:
    编译原理学习导论-作者四川大学唐良(转)初学者必看
    Ajax在chrome浏览器中测试调用失败解决办法
    sublime中输入法输入框只能在一个位置
    第三次作业
    第二次作业
    第一次作业
    2018年 大一下学期第零次作业
    14,15周作业
    第七周作业
    第六周作业
  • 原文地址:https://www.cnblogs.com/winslam/p/14413348.html
Copyright © 2020-2023  润新知