技術頻道

      動態鏈接庫在LabVIEW中的高級應用

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

      關鍵字:LabVIEW;動態鏈接庫;CLF節點

      1. 引言

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

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

      2. 實現方案及方案論證

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

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

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

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

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

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

      3. 軟件編程

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

        第一步:分析目標函數的參數類型

        SDK2000開發包中對獲得當前圖像的DIB數據函數的聲明為:

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

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

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

        第二步:編寫動態鏈接庫

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

        typedef struct

       ?。?int32 dimSize;

        uInt8 elt[1];

       ?。?TD1;//TD1的數據結構能被LabVIEW和新鏈接庫識別

        typedef TD1 **TD1Hdl;

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

        { long pp=0;

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

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

        return 0;

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

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

        lpdst = (*BitMapinfo)->elt;

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

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

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

        }

        編寫過程的幾點說明:

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

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

        MgErr NumericArrayResize(int32 typeCode, int32 numDims,

        UHandle *dataHP,int32 totalNewSize);

        ● 如果內存分配失敗,函數返回錯誤代碼。如果成功,還須修改數組結構中的dimSize,因為此函數不能自動修改此值。

        其它代碼的編寫類似于VC環境下的開發。代碼完成后,構件并產生最終的目標文件MySDK2000.dll。

        第三步:在LabVIEW中調用動態鏈接庫

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

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

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

      4. 結論

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

      參考文獻

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

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

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

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

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

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

      文章版權歸西部工控xbgk所有,未經許可不得轉載。

      主站蜘蛛池模板: 日本人真淫视频一区二区三区| 国产SUV精品一区二区88| 精品欧洲av无码一区二区三区| 国产精品一区二区久久精品涩爱| 国产福利电影一区二区三区久久老子无码午夜伦不 | 免费观看日本污污ww网站一区| 国产av熟女一区二区三区| 亚洲国产欧美日韩精品一区二区三区 | 国产香蕉一区二区在线网站| 亚洲国产专区一区| 国产一区精品视频| 国语对白一区二区三区| 在线日产精品一区| 国内自拍视频一区二区三区| 亚洲区精品久久一区二区三区| 久久青草精品一区二区三区| 最美女人体内射精一区二区| 亚洲国产一区二区视频网站| 美女视频一区二区| 日本一区二区三区精品视频| 久久青青草原一区二区| 国产成人久久一区二区不卡三区| 亚洲熟女www一区二区三区| 亚欧免费视频一区二区三区| 亚洲美女视频一区二区三区| 97av麻豆蜜桃一区二区| 亚洲一区中文字幕久久| 亚洲国产视频一区| 亚洲av综合av一区二区三区| 中文字幕乱码亚洲精品一区 | 国产一区在线观看免费| 春暖花开亚洲性无区一区二区| 成人免费一区二区无码视频| 天天视频一区二区三区 | 免费播放一区二区三区| 亚洲一区二区三区免费观看| 亚洲AV无码片一区二区三区 | 亚洲色大成网站www永久一区| 狠狠综合久久AV一区二区三区| 中文人妻无码一区二区三区| 无码人妻精品一区二区三区66|