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

来源:互联网 发布:pro tools 12.8.2 mac 编辑:程序博客网 时间:2024/06/04 19:02

操作环境: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进行标号定义1correct2 @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了、

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

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