vs2015+opencv生成DLL並分別靜態和動態呼叫
網路上關於vs生成dll的教程很多,解決方案繁雜,令人眼花繚亂,踩坑後推薦幾篇不錯的教程,親自測試可以通過的,我的除錯環境是vs2015 enterprise版+win10+opencv3.4.1。
教程1:最簡單的DLL生成與呼叫教程:作者採用了宣告類進行打包的方法來呼叫。
教程2:進階的DLL生成與呼叫教程,包含了opencv第三方lib和dll的呼叫與打包,生成的DLL可獨立於opencv環境執行。採用的是打包函式的方法,本人推薦這種方法,比較簡單易懂。
教程3:教程2中採用了靜態呼叫方法,且沒有給出多個函式的匯出宣告,於是我參考教程3完成了多函式匯出宣告與動態呼叫。
1.需求分析:
將一個基於opecv的影象超解析度程式打包成DLL,並測試。介面傳入的引數是Mat格式的影象,結果是imshow超解析度後的影象。
2.新建DLL工程
1. 建立無匯出符號的dll空專案;
2. 然後就是將之前寫的函式程式碼複製到原始檔中的Bleed.cpp中,其它兩個cpp不要管。
複製完畢後,點開Bleed.cpp然後對要呼叫的函式前面加上__declspec(dllexport),如圖中所示:
int Bleeding(Mat srcImage) 變為__declspec(dllexport) int Bleeding(Mat srcImage)
作為匯出函式宣告。
3. 建立原始檔Source.def
新增->新建->visual C++ ->模組定義檔案(.def)
LIBRARY "Bleed" EXPORTS Bleeding
- 在此檔案第一行引號中填你的專案名稱即可,EXPORTS下面列出要生成的函式名稱,若有多個匯出函式,則 格式:“名稱 @序號”)如:
LIBRARY "DLLGenerator"
EXPORTS
Add @1
Mul @2
這個例子匯出了Add和Mul兩個函式。4. 然後在右鍵點生成解決方案。
在工程目錄下會發現生成的Bleed.dll和Bleed.lib檔案。
3.靜態呼叫DLL
DLL的呼叫可分為動態呼叫和靜態呼叫兩種,靜態呼叫以來.h,.lib以及.dll檔案,而動態呼叫僅需要dll檔案。先講下如何靜態呼叫DLL:
1. 在專案管理器裡,右鍵單擊解決方案,新增/新建專案C++/Win32控制檯應用程式,命名。選擇沒有預編譯頭。
2. 新增測試程式碼
在原始檔的test_Bleed.cpp新增以下內容
// test_Bleed.cpp : 定義控制檯應用程式的入口點。
//
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
using namespace std;
#pragma comment(lib, "Bleed.lib") //呼叫dll檔案時候必須用到的
void Bleeding(); //對剛才寫好的處理函式進行宣告
//主函式
int main()
{
Bleeding();
return 0;
}
3. 生成解決方案,現在肯定是很多錯誤; 4.將dll和lib檔案拷貝到debug資料夾下,與exe檔案是同一個資料夾,另外,之前dll引用的檔案也都複製到現在這個專案的與cpp同一資料夾下;
5.右鍵專案名字選擇屬性,->配置屬性->VC++目錄->常規-庫目錄,選擇你放置了lib的debug資料夾。
->配置屬性->連結器-輸入-附加依賴項-編輯加入lib的檔名(全名包含字尾)-確認
6.生成,執行即可
4.動態呼叫DLL
1. 刪掉靜態呼叫時配置的lib和連結器選線: 刪除:右鍵專案名字選擇屬性,->配置屬性->VC++目錄->常規-庫目錄,選擇你放置了lib的debug資料夾。刪除:配置屬性->連結器-輸入-附加依賴項-編輯加入lib的檔名(全名包含字尾)-確認
2. 在原始檔中test_dll.cpp新增以下程式碼:
#include "stdafx.h"
#include <stdio.h>
#include <iostream>
#include <Windows.h>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
typedef int(*Dllfun)(Mat);
int _tmain(int argc, _TCHAR* argv[])
{
Dllfun Bleed;
HINSTANCE hInst = LoadLibrary(L"Bleed.dll");
if (!hInst)
{
printf("載入dll失敗!\n");
}
Bleed = (Dllfun)GetProcAddress(hInst, "Bleeding");
Mat srcImage = imread("E:\\JMCpp\\000024.jpg");
if (!srcImage.data)
return -1;
Bleed(srcImage);
::FreeLibrary(hInst);
return 0;
}
因為測試程式使用了opencv的imread函式,所以#include了opencv的庫,若不適用imread,DLL可以脫離opencv使用。