技術(shù)頻道

      動態(tài)鏈接庫在LabVIEW中的高級應用

      摘 要:LabVIEW中的提供了調(diào)用共享庫函數(shù)的接口,但是一些現(xiàn)成的函數(shù)庫卻因為接口參數(shù)類型不同而不能在LabVIEW中使用。利用重新編寫動態(tài)鏈接庫的方法可以建立舊函數(shù)庫與LabVIEW聯(lián)系的通道,提高現(xiàn)有資源的利用率。本文以SDK2000圖像采集卡為例,介紹具體的實現(xiàn)過程。

      關(guān)鍵字:LabVIEW;動態(tài)鏈接庫;CLF節(jié)點

      1. 引言

        實驗室虛擬儀器工作平臺是美國國家儀器公司研制的一種通用程序開發(fā)系統(tǒng),以其強大的數(shù)據(jù)采集、數(shù)據(jù)處理、數(shù)據(jù)分析和儀器控制功能在現(xiàn)代測控領(lǐng)域中得到了廣泛的應用。NI公司在推出LabVIEW語言同時,也推出了一系列的數(shù)據(jù)采集卡,但實際應用中往往會用到第三方廠家生產(chǎn)DAQ卡,在這種情況下就需要使用LabVIEW提供的外部程序接口。

        LabVIEW的“調(diào)用函數(shù)庫節(jié)點(CLF節(jié)點)”提供了調(diào)用標準函數(shù)和用戶自定義函數(shù)的通用方法,對于LabVIEW不支持的硬件設(shè)備大部分采用這種方法進行驅(qū)動。但是CLF節(jié)點也存在不足,使用中遇到最多的問題是參數(shù)類型不匹配。使用重寫動態(tài)鏈接庫的方法,一方面可以兼容舊函數(shù)庫的參數(shù)類型,另一方發(fā)面可以獲得LabVIEW提供的高級函數(shù)庫應用。以下以SDK2000圖像采集卡為例,介紹重寫函數(shù)庫的基本原理和程序編寫過程。

      2. 實現(xiàn)方案及方案論證

        SDK2000圖像采集卡提供的Visual C++ IDE 程序開發(fā)包包含了外部程序調(diào)用的共享函數(shù)庫,但是有些函數(shù)不能直接用CLF節(jié)點進行調(diào)用。主要有兩個原因:庫函數(shù)的參數(shù)類型與LabVIEW不兼容;圖形化語言對于一些底層操作不易實現(xiàn)。SDK2000圖像采集卡提供的庫函數(shù)含有LabVIEW不支持的數(shù)據(jù)類型,并且很多函數(shù)涉及到一些底層操作,如文件讀取和內(nèi)存管理。為了正確調(diào)用函數(shù)并返回有效數(shù)據(jù),解決這兩個問題是關(guān)鍵。

        LabVIEW僅提供最基本的數(shù)據(jù)類型,雖然可以在CLF節(jié)點參數(shù)設(shè)置中選擇“Adapt toType”,但只能夠傳遞LabVIEW內(nèi)部使用的參數(shù)類型而已,而共享庫函數(shù)使用上百種非標準數(shù)據(jù)類型。參數(shù)類型不匹配可分為兩種情況:

        ● 非標準數(shù)據(jù)類型定義。很多程序和函數(shù)用到一些非標準的類型定義,例如它們常常用char、short和long的類型定義代替Windows API使用的BYTE、WORD和DWORD。這種情況下要正確調(diào)用這些程序和函數(shù),必須找到這些參數(shù)在LabVIEW中同等的數(shù)據(jù)類型。

        ● 以結(jié)構(gòu)或者類作為參數(shù)。一些程序和函數(shù)使用結(jié)構(gòu)或者類作為參數(shù),但是LabVIEW并不能夠識別這些參數(shù)的數(shù)據(jù)結(jié)構(gòu)。為了正確調(diào)用這些庫函數(shù),LabVIEW提供了兩種解決辦法:使用CIN節(jié)點或者重寫函數(shù)庫對這些函數(shù)進行重新封裝,使這些函數(shù)的輸入輸出參數(shù)能夠符合LabVIEW的標準。

        SDK2000提供的共享函數(shù)庫使用了很多LabVIEW不支持的參數(shù)類型,如RECT、VIDEOSTREAMINFO等。為了正確調(diào)用這些函數(shù),必須用CIN節(jié)點或者重寫函數(shù)庫的方法對這些函數(shù)進行重新封裝。相對而言,重新編寫動態(tài)鏈接庫方法比使用CIN節(jié)點更為常用。因為CIN代碼直接嵌入到VI程序代碼里,對于編程器的限制比較高,所以一般不采用CIN節(jié)點。

        重新編寫動態(tài)鏈接庫的另一個原因,是為了獲得LabVIEW提供的高級函數(shù)庫應用。LabVIEW提供了在代碼開發(fā)環(huán)境下的高級函數(shù)庫,這些函數(shù)是針對于LabVIEW使用的數(shù)據(jù)類型,如下面所介紹的NumericArrayResize()函數(shù)。NumericArrayResize()函數(shù)用于動態(tài)改變數(shù)組的大小,不過只適合于LabVIEW使用的數(shù)組結(jié)構(gòu)。LabVIEW高級函數(shù)庫還包含了一些底層操作,如文件讀寫與內(nèi)存分配等等,不存在參數(shù)類型不同和底層操作困難的問題。

      3. 軟件編程

        由于需要重寫的函數(shù)比較多,這里僅以重寫保存DIB圖像數(shù)據(jù)函數(shù)為例,說明重寫函數(shù)庫的編寫過程。新函數(shù)GetDib()對原函數(shù)DSStream_GetCurrentDib()進行了封裝,其作用是向原函數(shù)傳遞有效參數(shù)并返回LabVIEW能識別的數(shù)據(jù)。使用的編程環(huán)境為Visual C++6.0。

        第一步:分析目標函數(shù)的參數(shù)類型

        SDK2000開發(fā)包中對獲得當前圖像的DIB數(shù)據(jù)函數(shù)的聲明為:

        HRESULT DSStream_GetCurrentDib(int iCardID,BYTE* pBuffer,long* pSize)

        pBuffer指向預分配的內(nèi)存,值為NULL時,pSize得到保存圖像需要的內(nèi)存大小,若pBuffer不為NULL,函數(shù)將DIB圖像數(shù)據(jù)保存到從pBuffer開始,長度為(*pSize)的內(nèi)存區(qū)域。CLF節(jié)點不能直接調(diào)用該函數(shù),因為LabVIEW編程環(huán)境下沒有提供內(nèi)存管理機制,并且CLF節(jié)點不能把指向預分配內(nèi)存的指針傳遞給該函數(shù),所以必須對這個函數(shù)進行重新封裝。

        圖像的DIB數(shù)據(jù)是非數(shù)字型的數(shù)據(jù),為了返回LabVIEW能夠識別的數(shù)據(jù),可以選擇字符串或者單字節(jié)數(shù)組作為數(shù)據(jù)的載體,但是由于數(shù)據(jù)中包含了十進制的0,所以只能用單字節(jié)數(shù)組作為載體,并且為了能夠動態(tài)改變數(shù)組的大小,必須以數(shù)組的句柄作為傳遞參數(shù)。因為在LabVIEW提供的高級函數(shù)庫中,所有改變數(shù)組、字符串大小的函數(shù)都是針對于句柄進行的。

        第二步:編寫動態(tài)鏈接庫

        在VC中使用MFC Application(dll)建立一個名字為MySDK2000的工程,然后在MySDK2000.cpp中鍵入以下代碼:

        typedef struct

        { int32 dimSize;

        uInt8 elt[1];

        } TD1;//TD1的數(shù)據(jù)結(jié)構(gòu)能被LabVIEW和新鏈接庫識別

        typedef TD1 **TD1Hdl;

        extern "C" __declspec(dllexport) long GetDib(TD1Hdl BitMapinfo)//BitMapinfo為數(shù)組的句柄

        { long pp=0;

        hr=DSStream_GetCurrentDib(m_iCardID, NULL, &pp);//得到保存圖像需要的內(nèi)存大小

        if (NumericArrayResize(uB,1L,(UHandle*)&BitMapinfo,pp))//改變數(shù)組物理大小

        return 0;

        (*BitMapinfo)->dimSize = pp;//改變數(shù)組大小的標志

        BYTE* lpdst; // 指向緩存DIB圖像的指針

        lpdst = (*BitMapinfo)->elt;

        hr=DSStream_GetCurrentDib(m_iCardID, lpdst, &pp);//將當前圖像的DIB數(shù)據(jù)保存到內(nèi)存中

        BITMAPINFO* pInfo = (BITMAPINFO*)lpdst;//位圖文件頭指針

        return pInfo->bmiHeader.biSize;//返回位圖信息頭的數(shù)據(jù)長度

        }

        編寫過程的幾點說明:

        ● 為了正確使用LabVIEW中的數(shù)據(jù)類型,必須在MySDK2000.cpp中手工加上#include “extcode.h”的聲明。頭文件”extcode.h”中定義了CIN和外部子程序所用到的基本數(shù)據(jù)類型和許多函數(shù)等,用以解決某些常量和數(shù)據(jù)類型與系統(tǒng)頭文件的沖突。

        ● 為了能夠在VC中調(diào)用LabVIEW的函數(shù)庫,必須把CINTools目錄下LabVIEW.lib包含在工程里。使用NumericArrayResize()函數(shù)用以動態(tài)改變數(shù)組的長度,它的功能和WIN32函數(shù)LocalAlloc()具有相似的功能。它的函數(shù)聲明如下:

        MgErr NumericArrayResize(int32 typeCode, int32 numDims,

        UHandle *dataHP,int32 totalNewSize);

        ● 如果內(nèi)存分配失敗,函數(shù)返回錯誤代碼。如果成功,還須修改數(shù)組結(jié)構(gòu)中的dimSize,因為此函數(shù)不能自動修改此值。

        其它代碼的編寫類似于VC環(huán)境下的開發(fā)。代碼完成后,構(gòu)件并產(chǎn)生最終的目標文件MySDK2000.dll。

        第三步:在LabVIEW中調(diào)用動態(tài)鏈接庫

        配置CLF節(jié)點的各項參數(shù)。第一個選項為函數(shù)庫文件名和路徑,選擇剛才編譯的文件MySDK2000.dll;第二個選項為函數(shù)名,選擇GetDib;第三項設(shè)置返回和傳遞參數(shù)。具體設(shè)置如下表:

        其它選項保持默認設(shè)置。程序框圖如下:

        為了弄清楚CLF運行時傳遞參數(shù)和返回參數(shù)的原型,可以在CLF節(jié)點上右鍵彈出菜單中選擇“Creat.c File…”,然后在文本編程環(huán)境下察看它的參數(shù)原型。這些參數(shù)原型其實就是LabVIEW使用到的數(shù)據(jù)結(jié)構(gòu),如上面說看到的數(shù)組結(jié)構(gòu)TD1,TD1為LabVIEW一維數(shù)組的數(shù)據(jù)結(jié)構(gòu)。

      4. 結(jié)論

        通過對原有函數(shù)的封裝,函數(shù)將圖像卡采集的DIB數(shù)據(jù)以數(shù)組形式返回給LabVIEW,LabVIEW將對這些數(shù)據(jù)進行進一步的處理,如二值化、邊緣分析等等。實踐證明,通過重寫動態(tài)鏈接庫的方法,第三方DAQ設(shè)備可以更協(xié)調(diào)地使用于LabVIEW開發(fā)環(huán)境中。

      參考文獻

        [1]. Using External Code in LabVIEW,National Instruments Corporation,2001.

        [2]. David J.Kruglinski,著,潘愛民 王國印,譯. Visual C++ 技術(shù)內(nèi)幕(第五版)[M].北京:清華大學出版社,2002.

        [3]. 楊樂平,李海濤,等. LabVIEW高級程序設(shè)計[M]. 北京:清華大學出版社,2003.

        [4]. 林康紅,唐海峰,奉玲,等. 動態(tài)鏈接庫DLL在虛擬儀器中的應用[J].計算機應用,2002,5:56-57.

        [5]. 陶以政,潘振顯.怎樣在LabVIEW中調(diào)用Win32動態(tài)鏈接庫[J].計算機應用,2000,20(6):72-73.

        [6]. 張輝,郁凱元,龍濤,等.基于LabVIEW軟件的動態(tài)鏈接庫和數(shù)據(jù)采集[J].儀表技術(shù),2002,6:36-37.

      文章版權(quán)歸西部工控xbgk所有,未經(jīng)許可不得轉(zhuǎn)載。

      主站蜘蛛池模板: 韩国美女vip福利一区| 日本大香伊一区二区三区| 久久影院亚洲一区| 亚洲日本一区二区三区| 福利视频一区二区牛牛| 亚洲一区精品视频在线 | 中文字幕av一区| 中文人妻av高清一区二区| 国产成人一区二区动漫精品| 精品日韩亚洲AV无码一区二区三区| 爆乳熟妇一区二区三区霸乳| 无码av中文一区二区三区桃花岛| 99久久综合狠狠综合久久一区| 人妻少妇AV无码一区二区| 精品国产亚洲一区二区在线观看| 韩国一区二区三区| 亚洲丰满熟女一区二区v| 精品亚洲A∨无码一区二区三区| 日韩人妻无码一区二区三区久久99 | 精品爆乳一区二区三区无码av| 久久国产精品一区二区| 中文字幕精品亚洲无线码一区应用| 国产精品久久久久一区二区| 在线播放精品一区二区啪视频| 亚洲日韩中文字幕一区| 亚洲一区AV无码少妇电影| 精品欧洲av无码一区二区| 久久精品一区二区三区AV| 亚欧免费视频一区二区三区 | 一区二区在线视频免费观看| 国产一区中文字幕在线观看| 国产人妖视频一区二区破除| 免费一区二区三区四区五区| 美女视频免费看一区二区 | 在线观看国产一区二区三区| 日韩精品一区二区三区毛片| 国产肥熟女视频一区二区三区| 国产在线精品一区在线观看| 精彩视频一区二区| 中文字幕在线无码一区| 久久国产午夜一区二区福利|