1. 程式人生 > >matlab函式編譯成庫供C++呼叫(非常詳細)

matlab函式編譯成庫供C++呼叫(非常詳細)

MATLAB具有著很高的計算效能,一些演算法用MATLAB很容易實現,而用C++很難實現,如果想在C++中呼叫MATLAB編寫的函式,可以將該函式編譯成庫檔案,之後在C++中對其進行呼叫。

本文詳細講解如何將MATLAB函式編譯成庫,並在C++中進行呼叫。方法可行,本人親測。

第一步、在MATLAB中的命令列視窗中輸入mex -setup,會出現如下介面。

mex -setup

第二步、點選介面中的“mex -setup C++”,出現如下提示。

mex -setup C++

第三步、之後就是進行對MATLAB中的function的編譯了。這裡,我的函式名為phasecong,實現的是影象相位一致性的計算。如下圖所示。

這個函式是一位大牛學者寫的,原本是有多個輸入和多個輸出的,但是為了編譯方便和後續呼叫方便,我把其他幾個引數刪掉了,只保留了一個輸入矩陣和一個輸出矩陣。

這樣做的好處是可以減少編譯和調用出錯的概率。編譯方法見第四步。

phasecong

第四步、下面就是對function進行編譯了,編譯的命令為:mcc -W cpplib:pc -T link:lib phasecong

這條命令中pc表示的是想要生成的庫的名稱,可以自己定,最後面的phasecong表示的是要編譯的函式的名,注意函式名後面不要加.m字尾。其他的引數都不用改。

如下圖所示。

編譯

第五步、輸入完上面的命令後就是等待MATLAB編譯完成了,我當時編譯好像用了30秒左右的時間。

編譯完成後就會出現編譯成功的提示,如下圖所示。

需要注意的是,在編譯時,當前資料夾一定要為function所在的資料夾。

編譯成功


第六步、經過上面的編譯後,在該資料夾下就會生成.h .cpp .lib .dll這四個檔案,因為我設定的輸出的庫名稱為pc,因此我這裡生成pc.h pc.cpp pc.lib pc.dll這四個檔案。

生成的檔案

第七步、接下來就是將生成的這四個檔案加入到我們的C++工程中了。

將這四個檔案放在C++工程的資料夾中,最好在該資料夾中新建兩個資料夾,分別命名為lib和include,因為後面我們還需要引入其他的庫檔案和標頭檔案,這樣做可以讓檔案更整齊。然後將pc.lib放入lib資料夾,將pc.h放入include資料夾。然後在VS中右鍵專案,點選屬性,在屬性中選擇“配置屬性”->“VC++目錄”->“包含目錄”,將剛才建立的include資料夾包含進去,如下圖所示。其他的屬性都不用改。

vs屬性

這樣我們就將標頭檔案包含了進去,之後進行載入lib檔案,這裡我們使用靜態載入方式,在工程檔案中加入這樣一條語句:

#pragma comment(lib, ".\\lib\\pc.lib" )
對於pc.dll和pc.cpp檔案,值需要將其放在工程目錄下就可以,不用進行配置。

這樣就完成了對這四個檔案的配置。

第八步、配置好生成的這四個檔案後就可以執行C++的程式了,但是點選執行後應該會報錯(通常一定會報錯),不要怕,這是因為我們前面生成的這四個檔案是需要依賴其他的庫和標頭檔案才能工作的。我們根據報錯的資訊可以知道缺少的標頭檔案,例如下圖這個錯誤:


通過這個錯誤我們就可以知道,我們的專案中缺少mat.h這個標頭檔案,這時我們就要找到這個標頭檔案並將其加入到include資料夾中。到哪裡去找呢,在這個資料夾中“D:\Program Files\MATLAB\R2014b\extern\include”。重複這一操作,直到不再提示這種錯誤。這一操作需要重複很多次,像我這個專案需要加入下圖這麼多的標頭檔案。


之後還需要加入額外的lib庫檔案,具體加入哪些lib檔案,需要根據上面的這些標頭檔案而定,我們到資料夾“D:\Program Files\MATLAB\R2014b\extern\lib\win64\microsoft”中(因為我的MATLAB是64位的,所以在win64資料夾下,如果大家的MATLAB是32位的,那麼估計是在win32資料夾下,大家自己找一下),尋找上面這些標頭檔案同名的lib檔案,不過並不是每個標頭檔案都能找到同名的lib檔案,不過不要緊,我們只要把能找到的lib檔案複製到工程目錄下的lib資料夾中即可,除了這些lib檔案之外,還需要加上“libmat.lib”和“libmx.lib”這兩個檔案,這兩個檔案好像包括著必要的型別的定義之類的吧。搞定之後我的lib資料夾中有下圖這些個檔案。


這些lib的載入方式與之前我們說的pc.lib的載入方式相同,如下圖所示。


進行到此,我們所有的配置就都搞定了,如果沒有意外的話,C++的專案編譯就可以通過了,

但是雖然編譯通過了,在執行的過程中還是有可能提示缺少某個庫檔案,我們只需要採用同樣的方法把那些庫檔案加到專案裡即可,比如我這個程式還提示我缺少mclmcr.dll這個檔案,我就把這個檔案複製到工程目錄下就可以了,所需的dll檔案通常都在“D:\Program Files\MATLAB\R2014b\bin\win64”這個資料夾可以找到。

至此我們就完成了MATLAB函式的編譯和C++呼叫的整個過程。

最後是幾點提示:

1、我這裡使用的是MATLAB2014a和vs2013。

2、如果使用的MATLAB是64位的版本,那麼C++的程式也要在x64下配置!!!!!!!

      如果使用的MATLAB是32位的版本,那麼C++的程式也要在win32下配置!!!!!!

      這點非常重要!!!!!!!!


3、MATLAB函式的輸入和輸出引數通常都是矩陣,在C++中矩陣變數使用mwArray這個型別,這個類的使用方法可以看我下面貼的程式碼,也可以在網上找教程。

4、在C++程式中,我們呼叫這個函式的名稱與MATLAB中定義的函式名稱相同,這個函式是在MATLAB編譯後生成的標頭檔案中進行的宣告,例如我這裡是在pc.h中。

5、在C++程式中,在定義輸入陣列和輸出陣列時,最好使用動態陣列,因為傳統的陣列是在棧中分配記憶體,這樣會造成記憶體溢位。

最後為了更直觀的展示在C++中如何對這些個庫檔案進行的呼叫以及如何使用這個函式,我在這裡貼上了C++程式的原始碼。

// pcproj.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include "pc.h"
#include <iostream>
#include <fstream>

using namespace std; 

#pragma comment(lib, ".\\lib\\pc.lib" )
#pragma comment(lib, ".\\lib\\mclmcrrt.lib")
#pragma comment(lib, ".\\lib\\libmx.lib")
#pragma comment(lib, ".\\lib\\libmat.lib")
#pragma comment(lib, ".\\lib\\mclmcr.lib")

#define WIDTH 512
#define HEIGHT 512

int _tmain(int argc, _TCHAR* argv[])
{
	//mclInitializeApplication(NULL, 0);
	//mclmcrInitialize();

	UINT8 *img_befor = new UINT8[WIDTH*HEIGHT];
	DOUBLE *img_after = new DOUBLE[WIDTH*HEIGHT];

	int data;
	double ddata;
	FILE *fp;

	errno_t err = fopen_s(&fp, "pixel.txt", "r");
	if (err!=0){
		cout << "open pic fail!" << endl;
		return 0;
	}

	for (int i = 0; i < WIDTH; i++){
		for (int j = 0; j < HEIGHT; j++){
			fscanf_s(fp, "%d", &data);
			img_befor[i*WIDTH + j] = data;
		}
	}

	fclose(fp);
	fp = NULL;

	pcInitialize();

	mwArray img_input_array(HEIGHT, WIDTH, mxUINT8_CLASS, mxREAL);
	mwArray img_output_array(HEIGHT, WIDTH, mxDOUBLE_CLASS, mxREAL);
	int nargout = 1;

	img_input_array.SetData(img_befor, HEIGHT*WIDTH);

	phasecong(nargout,img_output_array,img_input_array);
	
	img_output_array.GetData(img_after, HEIGHT*WIDTH);

	pcTerminate();

	//將結果寫到檔案
	err = fopen_s(&fp, "pixel_after.txt", "w");
	if (err != 0){
		cout << "open pic_after fail!" << endl;
	}
	else{
		//寫檔案
		for (int i = 0; i < WIDTH; i++){
			for (int j = 0; j < HEIGHT; j++){
				ddata = img_after[i*WIDTH + j];
				fprintf(fp, "%.4f ", ddata);
			}
			fprintf(fp, "\n");
		}
	}
	fclose(fp);
	fp = NULL;


	return 0;
}


相關推薦

matlab函式編譯C++呼叫非常詳細

MATLAB具有著很高的計算效能,一些演算法用MATLAB很容易實現,而用C++很難實現,如果想在C++中呼叫MATLAB編寫的函式,可以將該函式編譯成庫檔案,之後在C++中對其進行呼叫。 本文詳細講解如何將MATLAB函式編譯成庫,並在C++中進行呼叫。方法可行,本人親測

matlab2014a + win764bit + vs2013混合程式設計.m轉dllC++呼叫

在matlab中可以通過mbuild工具將.m檔案編譯成dll檔案供外部的C++程式呼叫,這樣就可以實現matlab和C++混合程式設計的目的。 1. 使用matlab生成dll檔案 1.1 首先需要帶有mcc編譯器的matlab軟體,這個可以通過在

Excel 函式 - VLookup 常見問題和使用技巧詳細

相信大家工作中用到的最多最複雜的查詢函式就是 Vlookup了,它真的很強大和實用,解決了工作中 90%的資料查詢和匹配問題。我工作中最先接觸,用的最多的也是 Vlookup 函式,這裡我總結一下我在使用中常遇到的一些問題和使用技巧,希望它能讓你 v 的更有成功。此文也獻給和我一起共事過的同

windows環境下caffe編譯以及python介面配置教程詳細

前言: 這週一直在搞caffe。編譯開原始碼是一件很痛苦的事情,在教程開始之前,還是建議同學要有耐心,不要怕麻煩,一步一步來,等到調通之日,發現確實沒有想象之中那麼複雜。 一、材料準備 1、下載ca

C++的 RTTI 觀念和用途非常詳細

自從1993年Bjarne Stroustrup 〔注1 〕提出有關C++ 的RTTI功能之建議﹐以及C++的異常處理(exception handling)需要RTTI;最近新推出的C++ 或多或少已提供RTTI。 然而,若不小心使用RTTI,可能會導致軟體彈性的降低。本文

用IKVMC將jar轉dllc#調用

又是 code 解決 轉化 自己的 不知道 使用方法 div 右擊 參考資料:https://www.cnblogs.com/Jack-Blog/p/4710848.html 用IKVMC將jar轉成dll供c#調用 前言 ikvmc介紹 ikvmc下載安裝 下載

分析簡單的c語言函式編譯得到的X86彙編程式碼VS2013

檢視原始碼生成的彙編程式碼:單步除錯->除錯->視窗->反彙編   總結: ①、函式被呼叫時,實參值賦值給函式棧中的形參,使用以下步驟:        I、call函式前實參值壓棧    &n

windows配置caffe及matlab/python介面編譯呼叫cpu/gpu

環境:windows 7+matlab2016a+vs2013 caffe下載地址:https://github.com/BVLC/caffe/tree/windows 1 進入caffe-windows的windows資料夾,Copy .\windows\CommonSettings.props.e

C#生成com元件形式的dllC++呼叫

①建立C#類庫(ClassLibrary)、設定AssemblyInfo.cs中的[assembly: ComVisible(true)]預設是false、或者在介面和類之前新增設定為true     [ComVisible(true)]     [Guid("E709D3

JNA呼叫C語言動態連結學習實踐總結指標模擬

最新因為專案需要,學習了一下JNA框架,在這裡記錄一下學習和使用心得,給大家分享,希望能幫助新手。 本文主要講解如何使用JNA框架輕鬆呼叫C語言動態連結庫,如何使用JNA模擬C語言引數(例如陣列、指標等)。 JNA(Java Native Access)框架

Android將Activity打jar包第三方呼叫解決資原始檔不能打包的問題

最近有一個需要,我們公司做了一個apk客戶端,然後其他的公司可以根據自己的需要來替換裡面的資源圖片,文字等一些資原始檔問題,我本來想這個簡單,用兩個工程直接替換裡面的資原始檔就行,老大說,這樣子不好,如果要改需要改兩個客戶端,而且還麻煩,叫我將所有的Activity

OWIN 自宿主模式WebApi專案,WebApi層作為單獨類OWIN呼叫

為什麼我們需要OWIN 過去,IIS作為.NET開發者來說是最常用的Web Server(沒有之一),源於微軟產品的緊耦合關係,我們不得不將Website、Web Application、Web API等部署在IIS上,事實上在2010年前並沒有什麼不妥,但隨著近些年來

C# DLL程式集的生成和呼叫

日期:2018年11月24日 環境:Window 10,VS2015 一、利用VS2015自帶的工具生成DLL   步驟:   1.利用C#準備一個.cs檔案; 1 using System; 2 3 public class MyMath 4 { 5 public MyM

6-3 使用函式驗證哥德巴赫猜想 10 分c語言解答附上我覺得注意點

6-3 使用函式驗證哥德巴赫猜想 (10 分) 本題要求實現一個判斷素數的簡單函式,並利用該函式驗證哥德巴赫猜想:任何一個不小於6的偶數均可表示為兩個奇素數之和。素數就是隻能被1和自身整除的正整數。注意:1不是素數,2是素數。 函式介面定義: int prime( int p ); vo

Python函式必須先定義、後呼叫函式呼叫函式例外

轉載:https://blog.csdn.net/songyunli1111/article/details/79302220 在函式中呼叫其他函式,不需要定義在前,呼叫在後 def fun1(a,b):     c=fun2(a,b)     pri

C++筆記十九——運算子過載函式

一、作用: 使複雜函式的理解更直觀,程式更加簡單易懂 二、運算子過載函式的形式是: 返回型別 operator 運算子符號(引數說明) {   //函式體的內部實現 } void operator +(Test&, Text&) { //函

Linux下G++編譯第一個C++程式Hello, world

安裝完各種環境工具之後(sudo apt install g++) 繼而新建一個空白文件Helloworl.cpp,貼上進最簡單的程式碼: #include<iostream>

LLVM與C++程式碼的相互呼叫全註釋

一、在C++中呼叫LLVM編寫的IR函式 #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/IR/Function.h" #include "llvm/IR/BasicBlock.h" #i

成員函式指標與高效能的C委託中篇

成員函式指標——為什麼那麼複雜?  類的成員函式和標準的C函式有一些不同。與被顯式宣告的引數相似,類的成員函式有一個隱藏的引數this,它指向一個類的例項。根據不同的編譯器,this或者被看作內部的一個正常的引數,或者會被特別對待(比如,在VC++中,this一般通過ECX暫