c++ opencv 下的动态链接库的创建和调用

操作环境:mac下的win10系统 x64+vs2015+opencv3.0
最近在学习图像,遇到了需要在c++进行动态链接库的设置,因为动态链接库会比静态链接库更加具有效率,故本文尽量从简单的方式记录下这几天的调试经验,以方便自己查阅和同道人学习。

一,动态链接库的创建

1、vs创建win32控制台程序,创建dll文件,并勾选导出符号(出现.h文件)。
创建文件

2、在设置文件名的头文件中进行导出函数声明:(我的文件名是correct1,所以在correct1.h中进行导出函数声明)

#ifdef CORRECT1_EXPORTS
#define CORRECT1_API __declspec(dllexport)
#else
#define CORRECT1_API __declspec(dllimport)
#endif
//以上均为vs自行生成,代表宏定义,就代表 CORRECT1_API 为输出符号。
#include "stdafx.h"
#include<opencv2/core/core.hpp>//由于用到了opencv,这是opencv的一些文件
#include<opencv2/highgui/highgui.hpp>
using namespace cv;

CORRECT1_API Mat  radio(Mat bright); 
//导出函数1,CORRECT1_API为导出声明,函数名是radio;函数类型是Mat类型,函数里面定义了一图像矩阵bright。
CORRECT1_API Mat  correct2(Mat before, Mat radio1);
//导出函数2,依然是mat类,其中有两个参数,before和radio1

3、进行def模块的声明:
源文件右键–添加–新建项–新建模板def文件。

LIBRARY correct1  
EXPORTS  
radio   @1   //对导出函数1进行标号定义1
correct2 @2 // 对导出函数2进行标号定义2

4、在cpp文件中进行定义函数


CORRECT1_API Mat  radio(Mat bright)
//to do sth;

CORRECT1_API Mat correct2(Mat before, Mat radio2)
//to to sth;

5、接下里进行编译,生成lib文件和dll文件。

如果这个时候进行运行程序,是一定会出错的,因为我们设定的是dll文件。
这里写图片描述

6、这个时候我们进行创建动态链接库的程序都进行完了。我们可以在工程目录下的x64中的debug文件中找到dll文件和lib文件。在后面的调用中会用到这些文件。
这里写图片描述

二、动态链接库的调用

首先,动态链接库的调用分为静态调用和动态调用。

静态调用需要dll文件,lib文件以及头文件。静态调用虽然理解简单,但每次的机械的操作步骤却并不怎么让人喜欢。由编译系统完成对DLL的加载和应用程序结束时DLL卸载的编码,Windows操作系统会负责控制DLL导入内存的次数。这种调用方式简单,能够满足通常的要求。通常采用的方法是把产生动态连接库时产生的.LIB文件(函数入口位置文件)加入到应用程序的工程中,想使用DLL中的函数时,只须在源文件中声明一下。
LIB文件包含了每一个DLL导出函数的符号名和可选择的标识号以及DLL文件名,不含有实际的代码。Lib文件包含的信息进入到生成的应用程序中,被调用的DLL文件会在应用程序加载时同时加载在到内存中。

动态调用只需要dll文件,即显式调用,是由编程者用API函数加载和卸载DLL来达到调用DLL的目的,比较复杂,但能更加有效地使用内存。

由于静态调用方法简单,需要把lib文件加入链接库,然后头文件加入,并且在cpp文件中#include”correct1.h”.并且需要b把创建的dll文件加入工程目录的debug下。然后就可以使用dll中的函数了。但我使用的是动态调用,因为很多时候并没有lib文件,只有别人给的dll文件,所以重点是动态调用。

动态调用是使用window系统中的loadlibrary和GetProcAddress,以及freelibrary函数进行的。

#include "stdafx.h"
#include"iostream"
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace std;
#include<Windows.h>
#include<time.h>

//第一步:为调用的两个导出函数设置类型声明 
typedef cv::Mat(*radioFun)(cv::Mat);//类型需与动态链接库里的函数类型一致
typedef cv::Mat(*correct2Fun)(cv::mat,cv::Mat);

int main()
{
    HMODULE hDll = LoadLibrary("correct1.dll");//读入动态链接库(需把dll文件放入工程下)
    if (hDll != NULL)
    {
        radioFun radio = (radioFun)GetProcAddress(hDll, MAKEINTRESOURCE(1));//读入函数1的地址
        if (radio != NULL)
        {
            cv::Mat radio1;
            radio1 = radio("bright.tif");//直接调用函数
            correct2Fun correct = (correct2Fun)GetProcAddress(hDll, MAKEINTRESOURCE(2));//获取函数2(即correct)的地址
            //correct(before, radio1);
            cv::imshow("radio", radio1);
            DWORD start_time = GetTickCount();//测算时间
            cv::Mat c = correct("before.tif", radio1);//调用第二个函数
            DWORD end_time = GetTickCount();

            cv::imshow("before", c);
            cout << "The run time is:" << (end_time - start_time) << "ms!" << endl;
            cv::waitKey(0);
        }

    }
        FreeLibrary(hDll);//释放库
    return 0;

}

由于Windows.h和opencv冲突,所以,只能用CV::Mat来表示。直接运行就OK了、

以后我会慢慢记录自己学到的知识,给自己留个备注,给大家做个参考。

路漫漫其修远兮,吾将上下而求索矣。共勉。

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值