我們知道,不是所有的板卡等硬件都提供了LabVIEW庫。所以動(dòng)態(tài)庫(DLL)是我們寫測控軟件繞不開的一個(gè)話題。本篇推送我們聊一聊什么是動(dòng)態(tài)庫、它是怎么實(shí)現(xiàn)的、在LabVIEW里我們又如何使用它。
什么是動(dòng)態(tài)庫? 動(dòng)態(tài)庫全稱動(dòng)態(tài)鏈接庫(Dynamic Link Library,DLL),?是一個(gè)包含函數(shù)和數(shù)據(jù)的模塊,它可以被其它應(yīng)用程序或者DLL使用。
動(dòng)態(tài)鏈接庫是怎么編寫的呢? 簡單來說就是通過dllexport標(biāo)識(shí)出需要導(dǎo)出的函數(shù)和變量。 我們分別看一下C和C++編寫的動(dòng)態(tài)庫代碼結(jié)構(gòu)。
C語言編寫的動(dòng)態(tài)鏈接庫代碼示例:
//CLib.h #ifndef C_LIB_H #define?C_LIB_H //需要導(dǎo)出的函數(shù)按照指定格式聲明 //extern?int?__declspec(dllexport)?exportFunction(type?para,?...); //通過DLL導(dǎo)出add函數(shù) extern int __declspec(dllexport) add(int x,int y); #endif //CLib.c #include?"Clib.h" //add函數(shù)實(shí)現(xiàn) int add( int x, int y ) { return x + y; }
C++語言編寫的動(dòng)態(tài)鏈接庫代碼示例:
?
//CplusplusLib.h #ifndef LIB_H #define LIB_H //需要導(dǎo)出的函數(shù)按照指定格式聲明 //extern?"C" int?__declspec(dllexport)?exportFunction(type?para,?...); //通過DLL導(dǎo)出add函數(shù) extern "C" int __declspec(dllexport) add(int x, int y); #endif //CplusplusLib.cpp #include "CplusplusLib.h" //add函數(shù)實(shí)現(xiàn) int add( int x, int y ) { return x + y; }與C語言編寫的動(dòng)態(tài)鏈接庫相比,不同的地方在于extern int “C” __declspec(dllexport) add(int x,int y) 這一導(dǎo)出語句,在C代碼中沒有”C” ,而在C++代碼中多了一個(gè)”C”。 原因是C++編譯器與C編譯器在對程序進(jìn)行編譯的時(shí)候,對函數(shù)聲明的編譯會(huì)有所區(qū)別。加上”C”,是為了告訴C++編譯器,使用C編譯器的方式對這一個(gè)函數(shù)聲明進(jìn)行編譯。這樣,在C程序調(diào)用C++寫的動(dòng)態(tài)鏈接庫的時(shí)候,不會(huì)發(fā)生因?yàn)閷ふ也坏綄?yīng)的函數(shù)名(編譯后的)而發(fā)生Link錯(cuò)誤。
LabVIEW如何調(diào)用動(dòng)態(tài)庫?
我們以某品牌數(shù)據(jù)采集卡為例,說明一下如何使用動(dòng)態(tài)庫。 安裝好驅(qū)動(dòng)后,我們可以找到該品牌數(shù)據(jù)采集卡提供的動(dòng)態(tài)庫函數(shù)和頭文件,D2K-Dask.dll和D2kDask.h。
方法1:直接調(diào)用 所謂直接調(diào)用,就是使用Call Library Function Node調(diào)用。這個(gè)VI位于Connectivity->Librarie&Executables分類下。 在程序框圖里放置Call Library Function Node,雙擊進(jìn)行設(shè)置。在Library name or path中設(shè)置到動(dòng)態(tài)庫文件,在Function name中選擇需要調(diào)用的函數(shù)(LabVIEW會(huì)自動(dòng)解析出該動(dòng)態(tài)庫導(dǎo)出的函數(shù)清單)。
例如我們選擇D2K_AI_VReadChannel函數(shù)。這里我們需要找到動(dòng)態(tài)庫的文檔,按照文檔里提供的函數(shù)說明為CalDl Library Function Node設(shè)置好D2K_AI_VReadChannel函數(shù)的參數(shù)和返回值。
I16 __stdcall D2K_AI_VReadChannel (U16 CardNumber, U16 Channel, F64 *voltage)將Call Library Function設(shè)置對話框切換到Parameters標(biāo)簽頁,設(shè)置好返回值和參數(shù)。error(return value)、cardNumber和channel都是值傳遞的參數(shù),“Type”選擇Numeric,“Data type”選擇Unsigned 16-bit Interger,“Pass”選擇Value;voltage是指向F64類型數(shù)據(jù)的指針,“Type”選擇Numeric,“Data type”選擇8-byte Double,“Pass”選擇Pointer to Value。
?
?
設(shè)置好之后的Call Library Function Node類似下圖,在左、右側(cè)連接好對應(yīng)參數(shù)即可調(diào)用D2K_AI_VReadChannel函數(shù)。
這個(gè)設(shè)置和調(diào)用過程,調(diào)用庫函數(shù)個(gè)數(shù)較少時(shí)還是可以接受的。如果庫函數(shù)的數(shù)量比較多,挨個(gè)設(shè)置很繁瑣也容易出錯(cuò)。針對這種情況,LabVIEW有更好的方法,也就是我們要介紹的方法2。
方法2:動(dòng)態(tài)庫封裝成VI庫 Tools->Import->Shared Library打開Import Shared Library工具。
Step1,打開Import Shared Library,選擇Create VIs for a shared library。
Step2,選擇動(dòng)態(tài)庫文件和對應(yīng)的頭文件。注意這里頭文件必須是C/C++規(guī)范的。
Step3,根據(jù)需要設(shè)置頭文件包含路徑和預(yù)處理定義。如果不需要,可以留空。
Step4,LabView自動(dòng)識(shí)別出動(dòng)態(tài)庫里可以封裝成VI導(dǎo)出的函數(shù)。
例如我們前面設(shè)置的D2K_AI_VReadChannel,這里自動(dòng)識(shí)別出函數(shù)原型來了。
Step5,設(shè)置VI庫名稱和存放路徑。路徑建議使用默認(rèn)路徑,放置在用戶庫里。
Step6,設(shè)置出錯(cuò)處理方式。
Step7,設(shè)置各個(gè)導(dǎo)出函數(shù)(VI函數(shù)),一般可選擇使用默認(rèn)設(shè)置。
Step8,LabVIEW給出一個(gè)即將要生成的VI庫的匯總信息。
Step9,生成中。
Step10,完成VI庫生成。
勾選“Open the generated library”可以打開生成的VI庫;勾選View the report可以查看有關(guān)所生成庫的報(bào)表。
打開剛才生成的VI庫,可以看到里面封裝了非常多的庫函數(shù)。這些庫函數(shù)如果按照方法1去挨個(gè)設(shè)置,顯然工作量是非常大的。
生成的動(dòng)態(tài)函數(shù)VI庫怎么使用呢?
在程序框圖里找到User Libraries,里面就有剛才我們生成的D2K-DaskVI庫。
VIs下面列出了所有庫函數(shù)對應(yīng)的VI,把你需要的拖放到程序框圖上,按照輸入輸出類型連接好就可以了。
比如D2K AI V Read Channel.vi,顯示Label、不勾選View as icon,如下圖,輸入輸出非常明了。
以上是C/C++動(dòng)態(tài)鏈接庫的基本知識(shí)和LabVIEW中如何使用C/C++動(dòng)態(tài)鏈接庫的方法介紹,希望能夠幫助到大家。
編輯:黃飛
?
評論
查看更多