VB調用動態(tài)鏈接庫教學文稿_第1頁
VB調用動態(tài)鏈接庫教學文稿_第2頁
VB調用動態(tài)鏈接庫教學文稿_第3頁
VB調用動態(tài)鏈接庫教學文稿_第4頁
VB調用動態(tài)鏈接庫教學文稿_第5頁
已閱讀5頁,還剩33頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、Good is good, but better carries it.精益求精,善益求善。VB調用動態(tài)鏈接庫-VB調用動態(tài)鏈接庫-Dll編程作為一種簡單易用的Windows開發(fā)環(huán)境,VisualBasic從一推出就受到了廣大編程人員的歡迎。它使程序員不必再直接面對紛繁復雜的Windows消息,而可以將精力主要集中在程序功能的實現(xiàn)上,大大提高了編程效率。但凡事有利必有弊。VB中高度的封裝和模塊化減輕了編程者的負擔,同時也使開發(fā)人員失去了許多訪問低層API函數(shù)和直接與Windows交互的機會。因此,相比而言,VB應用程序的執(zhí)行效率和功能比C/C+或Delphi生成的程序要差。為了解決這個問題,在

2、一個大型的VB開發(fā)應用中,直接調用WindowsAPI函數(shù)幾乎是不可避免的;同時,還有可能需要程序員自己用C/C+等開發(fā)一些動態(tài)連接庫,用于在VB中調用。本文主要討論在32位開發(fā)環(huán)境VisualBasic5.0中直接調用Windows95API函數(shù)或用戶生成的32位動態(tài)連接庫的方法與規(guī)則。Windows動態(tài)連接庫是包含數(shù)據(jù)和函數(shù)的模塊,可以被其它可執(zhí)行文件(EXE、DLL、OCX等)調用。動態(tài)連接庫包含兩種函數(shù):輸出(exported)函數(shù)和內部(internal)函數(shù)。輸出函數(shù)可以被其它模塊調用,而內部函數(shù)則只能在動態(tài)連接庫內部使用。盡管動態(tài)連接庫也能輸出數(shù)據(jù),但實際上它的數(shù)據(jù)通常是只在內部

3、使用的。使用動態(tài)連接庫的優(yōu)點是顯而易見的。將應用程序的一部分功能提取出來做成動態(tài)連接庫,不但減小了主應用程序的大小,提高了程序運行效率,還使它更加易于升級。多個應用程序共享一個動態(tài)連接庫還能有效地節(jié)省系統(tǒng)資源。正因為如此,在Windows系統(tǒng)中,動態(tài)連接庫得到了大量的使用。一般來說,動態(tài)連接庫都是以DLL為擴展名的文件,如Kernel32.dll、commdlg.dll等。但也有例外,如16位Windows的核心部件之一GDI.exe其實也是一個動態(tài)庫。編寫動態(tài)連接庫的工具很多,如VisualC+、BorlandC+、Delphi等,具體方法可以參見相關文檔。下面只以VisualC+5.0為例

4、,介紹一下開發(fā)應用于VisualBasic5.0的動態(tài)連接庫時應注意的問題(本文中所有涉及C/C+語言或編譯環(huán)境的地方,都以VC5為例;所有涉及VisualBasic的地方都以VB5為例)。作為一種32位Windows應用程序的開發(fā)工具,VB5生成的exe文件自然也都是32位的,通常情況下也只能調用32位的動態(tài)連接庫。但是,并不是所有的32位動態(tài)庫都能被VB生成的exe文件正確地識別。一般來說,自己編寫用于VB應用程序調用的動態(tài)連接庫時,應注意以下幾個方面的問題:1、生成動態(tài)庫時要使用_stdcall調用約定,而不能使用缺省的_cdecl調用約定;_stdcall約定通常用于32位API函數(shù)的

5、調用。2、在VC5中的定義文件(.def)中,必須列出輸出函數(shù)的函數(shù)名,以強制VC5系統(tǒng)將輸出函數(shù)的裝飾名(decoratedname)改成普通函數(shù)名;所謂裝飾名是VC的編譯器在編譯過程中生成的輸出函數(shù)名,它包含了用戶定義的函數(shù)名、函數(shù)參數(shù)及函數(shù)所在的類等多方面的信息。由于在VC5中定義文件不是必需的,因此工程不包含定義文件時VC5就按自己的約定將用戶定義的輸出函數(shù)名修改成裝飾名后放到輸出函數(shù)列表中,這樣的輸出函數(shù)在VB生成的應用程序中是不能正確調用的(除非聲明時使用Alias子句)。因此需要增加一個.def文件,其中列出用戶需要的函數(shù)名,以強制VC5不按裝飾名進行輸出。3、VC5中的編譯選項

6、結構成員對齊方式(structurememberalignment)應設成4字節(jié),其原因將在后文詳細介紹。4、由于在C中整型變量是4個字節(jié),而VB中的整型變量依然只有2個字節(jié),因此在C中聲明的整型(int)變量在VB中調用時要聲明為長整型(long),而C中的短整型(short)在VB中則要聲明成整型(integer);下表針對最常用的C語言數(shù)據(jù)類型列出了與之等價的VisualBasic類型(用于32位版本的Windows)。C語言數(shù)據(jù)類型在VisualBasic中聲明為調用時使用的表達式ATOMByValvariableAsInteger結果為Integer類型的表達式BOOLByValva

7、riableAsLong結果為Long類型的表達式BYTEByValvariableAsByte結果為Byte類型的表達式CHARByValvariableAsByte結果為Byte類型的表達式COLORREFByValvariableAsLong結果為Long類型的表達式DWORDByValvariableAsLong結果為Long類型的表達式HWND,HDC,HMENUByValvariableAsLong結果為Long類型的表達式等Windows句柄INT,UINTByValvariableAsLong結果為Long類型的表達式LONGByValvariableAsLong結果為Long

8、類型的表達式LPARAMByValvariableAsLong結果為Long類型的表達式LPDWORDvariableAsLong結果為Long類型的表達式LPINT,LPUINTvariableAsLong結果為Long類型的表達式LPRECTvariableAstype自定義類型的任意變量LPSTR,LPCSTRByValvariableAsString結果為String類型的表達式LPVOIDvariableAsAny任何變量(在傳遞字符串的時候使用ByVal)LPWORDvariableAsInteger結果為Integer類型的表達式LRESULTByValvariableAsLon

9、g結果為Long類型的表達式NULLAsAny或ByValNothing或ByValvariableAsLongByVal0&或VBNullStringSHORTByValvariableAsInteger結果為Integer類型的表達式VOIDSubprocedure不可用WORDByValvariableAsInteger結果為Integer類型的表達式WPARAMByValvariableAsLong結果為Long類型的表達式5、VB中進行32位動態(tài)庫的聲明時,函數(shù)名是大小寫敏感的。在獲得了需要的動態(tài)連接庫之后,就可以在VB中進行調用了。但是,由于VB不能驗證應用程序傳遞到動態(tài)連接庫中的

10、參數(shù)值是否正確,因此VB程序中大量的API調用可能會降低整個應用程序的穩(wěn)定性,也會增加以后維護的難度。所以,決定在VB程序中直接調用API函數(shù)時要慎重,但適當?shù)氖褂肁PI調用確實能夠有效地提高VB程序的性能。這之間的平衡需要編程人員根據(jù)實際情況來掌握。下面就具體介紹一下在VB中調用API函數(shù)時需要做的工作。要聲明一個DLL過程,首先需要在代碼窗口的通用(General)部分增加一個Declare語句。如果該過程返回一個值,應將其聲明為Function:DeclareFunctionpublicnameLiblibnameAliasalias(ByValvariableAstype,ByValv

11、ariableAstype.)AsType如果過程沒有返回值,可將其聲明為Sub:DeclareSubpublicnameLiblibnameAliasalias(ByValvariableAstype,ByValvariableAstype.)缺省情況下,在標準模塊中聲明的DLL過程,可以在應用程序的任何地方調用它。在其它類型的模塊中定義的DLL過程則是模塊私有的,必須在它們前面聲明Private關鍵字,以示區(qū)分。下面分別介紹聲明語句的各個組成部分。(一)、指定動態(tài)庫:Declare語句中的Lib子句用來告訴VisualBasic如何找到包含過程的.dll文件。如果引用的過程屬于Window

12、s核心庫(User32、Kernel32或GDI32),則可以不包含文件擴展名,如:DeclareFunctionGetTickCountLibkernel32AliasGetTickCount()AsLong對于其它動態(tài)連接庫,可以在Lib子句指定文件的路徑:DeclareFunctionlzCopyLibc:windowslzexpand.dll_(ByValSAsInteger,ByValDAsInteger)AsLong如果未指定libname的路徑,VisualBasic將按照下列順序查找該文件:.exe文件所在的目錄當前目錄Windows系統(tǒng)目錄Windows目錄Path環(huán)境變量中

13、的目錄下表中列出了常用的操作系統(tǒng)環(huán)境庫文件。動態(tài)鏈接庫描述Advapi32.dll高級API服務,支持大量的API(其中包括許多安全與注冊方面的調用)Comdlg32.dll通用對話框API庫Gdi32.dll圖形設備接口API庫Kernel32.dllWindows32位核心的API支持Lz32.dll32位壓縮例程Mpr.dll多接口路由器庫Netapi32.dll32位網(wǎng)絡API庫Shell32.dll32位ShellAPI庫User32.dll用戶接口例程庫Version.dll版本庫Winmm.dllWindows多媒體庫Winspool.drv后臺打印接口,包含后臺打印API調用。

14、對于Windows的系統(tǒng)API函數(shù),可以利用VB提供的工具APIViewer查找某一函數(shù)及其相關數(shù)據(jù)結構和常數(shù)的聲明,并復制到自己的程序中。(二)、使用別名:Declare語句中的Alias子句是一個可選的部分,用戶可以通過它所標識的別名對動態(tài)庫中的函數(shù)進行引用。例如,在下面的語句中,聲明了一個在VB中名為MyFunction的函數(shù),而它在動態(tài)庫Mydll.dll中最初的名字是MyFunctionX。PrivateDeclareFunctionMyFunctionLibMydll.dll_AliasMyFunctionX()AsLong需要注意的是,Alias子句中的函數(shù)名是大小寫敏感的,也就

15、是說,必須與函數(shù)在生成時的聲明(如在C源文件中的聲明)一致。這是因為32位動態(tài)庫與16位動態(tài)庫不同,其中的函數(shù)名是區(qū)分大小寫的。同樣道理,如果沒有使用Alias子句,那么在Function(或Sub)后的函數(shù)名也是區(qū)分大小寫的。通常在以下幾種情況時需要使用Alias子句:A.處理使用字符串的系統(tǒng)WindowsAPI過程如果調用的系統(tǒng)WindowsAPI過程要使用字符串,那么聲明語句中必須增加一個Alias子句,以指定正確的字符集。包含字符串的系統(tǒng)WindowsAPI函數(shù)實際有兩種格式:ANSI和Unicode(關于ANSI和Unicode兩種字符集的區(qū)別將在后面詳細闡述)。因此,在Window

16、s頭文件中,每個包含字符串的函數(shù)都同時有ANSI版本和Unicode版本。例如,下面是SetWindowText函數(shù)的兩種C語言描述??梢钥吹剑谝粋€描述將函數(shù)定義為SetWindowTextA,尾部的A表明它是一個ANSI函數(shù):WINUSERAPIBOOLWINAPISetWindowTextA(HWNDhWnd,LPCSTRlpString);第二個描述將它定義為SetWindowTextW,尾部的W表明它是一個Unicode函數(shù):WINUSERAPIBOOLWINAPISetWindowTextW(HWNDhWnd,LPCWSTRlpString);因為兩個函數(shù)實際的名稱都不是SetWi

17、ndowText,要引用正確的函數(shù)就必須增加一個Alias子句:PrivateDeclareFunctionSetWindowTextLibuser32_AliasSetWindowTextA(ByValhwndAsLong,ByVal_lpStringAsString)AsLong應當注意,對于VB中使用的系統(tǒng)WindowsAPI函數(shù),應該指定函數(shù)的ANSI版本,因為只有WindowsNT才支持Unicode版本,而Windows95不支持這個版本。僅當應用程序只運行在WindowsNT平臺上的時候才可以使用Unicode版本。B.函數(shù)名是不標準的名稱有時,個別的DLL過程的名稱不是有效的標

18、識符。例如,它可能包含了非法的字符(如連字符),或者名稱是VB的關鍵字(如GetObject)。在這種情況下,可以使用Alias關鍵字。例如,操作環(huán)境DLLs中的某些過程名以下劃線開始。盡管在VB標識符中允許使用標識符,但是下劃線不能作為標識符的第一個字符。為了使用這種過程,必須先聲明一個名稱合法的過程,然后用Alias子句引用過程的真實名稱:DeclareFunctionlopenLibkernel32Alias_lopen_(ByVallpPathNameAsString,ByValiReadWrite_AsLong)AsLong在上例中,lopen是VB中使用的過程名稱。而_lopen則

19、是動態(tài)連接庫中可以識別的名稱。C.使用序號標識DLL過程除了使用名稱之外,還可以使用序號來標識DLL過程。某些動態(tài)連接庫中不包含過程的名稱,在聲明它們包含的過程時必須使用序號。同使用名稱標識的DLL過程相比,如果使用序號,在最終的應用程序中消耗的內存將比較少,而且速度會快些。但是,一個具體的API的序號在不同的操作系統(tǒng)中可能是不同的。例如GetWindowsDirectory在Win95下的序號為432,而在WindowsNT4.0下為338??偠灾?,如果希望應用程序能夠在不同的操作系統(tǒng)下運行,那么最好不要使用序號來標識API過程。如果過程不屬于API,或者應用程序使用的范圍很有限,那么使用

20、序號還是有好處的。要使用序號來聲明DLL過程,Alias子句中的字符串需要包含過程的序號,并在序號的前面加一個數(shù)字標記字符(#)。例如,Windowskernel中的GetWindowsDirectory函數(shù)的序號為432;可以用下面的語句來聲明該DLL過程:DeclareFunctionGetWindowsDirectoryLibkernel32_Alias#432(ByVallpBufferAsString,_ByValnSizeAsLong)AsLong在這里,可以使用任意的合法名稱作為過程的名稱,VB將用序號在DLL中尋找過程。為了得到要聲明的過程的序號,可以使用Dumpbin.exe

21、等實用工具(Dumpbin.exe是MicrosoftVisualC+提供的一個實用工具,它的使用說明可以參見VC的文檔)。利用Dumpbin,可以提取出.dll文件中的各種信息,例如DLL中的函數(shù)列表,它們的序號以及與代碼有關的其它信息。(三)、使用值或引用傳遞在缺省的情況下,VB以引用方式傳遞所有參數(shù)(ByRef)。這意味著并沒有傳遞實際的參數(shù)值,VB只傳遞了數(shù)據(jù)的32位地址。另外有許多DLL過程要求參數(shù)以值方式傳遞(ByVal)。這意味著它們需要實際的數(shù)據(jù),而不是數(shù)據(jù)的內存地址。如果過程需要一個傳值參數(shù),而傳遞給它的參數(shù)是一個指針,那么由于得到了錯誤的數(shù)據(jù),該過程將不能正確地工作。要使參

22、數(shù)以使用值方式傳遞,在Declare語句中需要在參數(shù)聲明的前面加上ByVal關鍵字。例如InvertRect過程要求第一個參數(shù)用傳值方式傳遞,而第二個用引用方式傳遞:DeclareFunctionInvertRectLibuser32Alias_InvertRectA(ByValhdcAsLong,lpRectAsRECT)AsLong動態(tài)連接庫的參數(shù)傳遞是一個復雜的問題,也是VB中調用動態(tài)連接庫時最容易出現(xiàn)錯誤的地方。參數(shù)類型或傳遞方式的聲明錯誤都可能導致應用程序出現(xiàn)GPF(通用保護錯誤),甚至使操作系統(tǒng)崩潰,因此我們將在后面專門詳細地討論這個問題。(四)、靈活的參數(shù)類型某些DLL過程的同一

23、個參數(shù)能夠接受多種數(shù)據(jù)類型。如果需要傳遞多種類型的數(shù)據(jù),可以將參數(shù)聲明為AsAny,從而取消類型限制。例如,下面的聲明中的第三個參數(shù)(lpptAsAny)既可以傳遞一個POINT結構的數(shù)組,也可以傳遞一個RECT結構:DeclareFunctionMapWindowPointsLibuser32Alias_MapWindowPoints(ByValhwndFromAsLong,_ByValhwndToAsLong,lpptAsAny,_ByValcPointsAsLong)AsLongAsAny子句提供了一定的靈活性,但是,由于它不進行任何的類型檢查,風險也隨之增加。因此在使用AsAny子句時

24、,必須仔細檢查所有參數(shù)的類型。正確的函數(shù)聲明是在VB中調用動態(tài)連接庫的前提,但要想在VB中用對、用好動態(tài)庫中的函數(shù),僅僅有聲明還是遠遠不夠的。前面已經(jīng)說過,由于VB不能驗證應用程序傳遞到動態(tài)連接庫中的參數(shù)值是否正確,因此就要求程序員應對參數(shù)類型有非常詳細的了解,否則很容易引起應用程序發(fā)生通用保護錯或導致潛在的Bug,降低軟件的可靠性。下面將參數(shù)類型分為簡單數(shù)據(jù)類型、字符串、和用戶自定義類型三種分別進行討論。(1)、簡單數(shù)據(jù)類型:簡單數(shù)據(jù)類型是指Numeric數(shù)據(jù)類型(包括Integer、Long、Single、Double、Currency類型)、Byte數(shù)據(jù)類型和Boolean數(shù)據(jù)類型。它們

25、的共同的特點是結構簡單,操作系統(tǒng)在處理時不必進行特殊的轉換。簡單數(shù)據(jù)類型參數(shù)的傳遞比較簡單。我們知道,在VB中傳遞參數(shù)的方式有兩種:傳值(Byval)和傳址(ByRef),缺省的方式是傳址。所謂傳值,就是對一個變量的具體值進行傳遞;而傳址則是傳遞變量的地址。例如,在VB程序中需要將一個整型變量m=10的值傳進動態(tài)庫,如果用傳值方式,那么傳進動態(tài)庫的值就是10,而在傳址方式下,傳入的則是變量m的地址,相當于C/C+中&m的值。需要注意的是,以傳值方式傳進動態(tài)連接庫的變量,其值在動態(tài)庫中是不能被改變的;如果需要在動態(tài)連接庫中修改傳入?yún)?shù)的值,則必須使用傳址方式。一般來說,在VB和動態(tài)連接庫之間傳遞

26、單個的簡單數(shù)據(jù)類型,只要注意了以上幾個方面就可以了。當需要將一個簡單數(shù)據(jù)類型的整個數(shù)組傳進動態(tài)庫時,必須將相應參數(shù)聲明為傳址方式,然后把數(shù)組的第一個元素作為參數(shù)傳入,這樣在動態(tài)連接庫中就得到了數(shù)組的首地址,從而可以對整個數(shù)組進行訪問。例如,聲明了一個名為ReadArray的DLL過程,要求傳入一個整型數(shù)組aArray:DeclareFunctionReadArrayLibmydll.dll_(aArrayAsInteger)AsInteger在調用時可以采用如下方式:Dimret,I(5)asIntegerret=ReadArray(I(0)注釋:將整個數(shù)組傳入動態(tài)連接庫(2)、字符串參數(shù)的傳

27、遞:與簡單數(shù)據(jù)類型相比,字符串類型(String、String*n)的參數(shù)傳遞要復雜得多,這主要是Windows98API和VB使用的字符串類型不同的緣故。VB使用被稱為BSTR的String數(shù)據(jù)類型,它是由自動化(以前被稱為OLEAutomation)定義的數(shù)據(jù)類型。一個BSTR由頭部和字符串組成,頭部包含了字符串的長度信息,字符串中可以包含嵌入的null值。大部分的BSTR是Unicode的,即每個字符需要兩個字節(jié)。BSTR通常以兩字節(jié)的兩個null字符結束。下圖表示了一個BSTR類型的字符串。FunctionGetCharByte(ByValOneCharAsInteger,ByValI

28、sHighByteAsBoolean)AsByte注釋:該函數(shù)獲得一個字符的高字節(jié)或低字節(jié)IfIsHighByteThenIfOneChar=0ThenGetCharByte=CByte(OneChar256)注釋:右移8位,得到高字節(jié)ElseGetCharByte=CByte(OneCharAnd&H7FFF)256)Or&H80EndIfExitFunctionElseGetCharByte=CByte(OneCharAnd&HFF)注釋:屏蔽掉高字節(jié),得到低字節(jié)ExitFunctionEndIfEndFunctionSubStrToByte(StrToChangeAsString,Byt

29、eArray()AsByte)注釋:該函數(shù)將一個字符串轉換成字節(jié)數(shù)組DimLowBound,UpBoundAsIntegerDimi,count,lengthAsIntegerDimOneCharAsIntegercount=0length=Len(StrToChange)LowBound=LBound(ByteArray)UpBound=UBound(ByteArray)Fori=LowBoundToUpBoundByteArray(i)=0注釋:初始化字節(jié)數(shù)組NextFori=LowBoundToUpBoundcount=count+1Ifcount255)Or(OneChar0)Then

30、注釋:該字符是非ASCII字符ByteArray(i)=GetCharByte(OneChar,True)注釋:得到高字節(jié)i=i+1Ifi=0ThenGetCharByte=CByte(OneChar256)注釋:右移8位,得到高字節(jié)ElseGetCharByte=CByte(OneCharAnd&H7FFF)256)Or&H80EndIfExitFunctionElseGetCharByte=CByte(OneCharAnd&HFF)注釋:屏蔽掉高字節(jié),得到低字節(jié)ExitFunctionEndIfEndFunctionSubStrToByte(StrToChangeAsString,Byte

31、Array()AsByte)注釋:該函數(shù)將一個字符串轉換成字節(jié)數(shù)組DimLowBound,UpBoundAsIntegerDimi,count,lengthAsIntegerDimOneCharAsIntegercount=0length=Len(StrToChange)LowBound=LBound(ByteArray)UpBound=UBound(ByteArray)Fori=LowBoundToUpBoundByteArray(i)=0注釋:初始化字節(jié)數(shù)組NextFori=LowBoundToUpBoundcount=count+1Ifcount255)Or(OneChar0)Then注

32、釋:該字符是非ASCII字符ByteArray(i)=GetCharByte(OneChar,True)注釋:得到高字節(jié)i=i+1Ifi=UpBoundThenByteArray(i)=GetCharByte(OneChar,False)注釋:得到低字節(jié)Else注釋:該字符是ASCII字符ByteArray(i)=OneCharEndIfElseExitForEndIfNextEndSubSubChangeStrAryToByte(StrAry()AsString,ByteAry()AsByte)注釋:將字符串數(shù)組轉換成字節(jié)數(shù)組DimLowBound,UpBoundAsIntegerDimi,

33、count,StartPos,MaxLenAsIntegerDimTmpByte()AsByteLowBound=LBound(StrAry)UpBound=UBound(StrAry)count=0ReDimByteAry(0)Fori=LowBoundToUpBoundMaxLen=LenB(StrAry(i)ReDimTmpByte(MaxLen+1)ReDimPreserveByteAry(count+MaxLen+1)CallStrToByte(StrAry(i),TmpByte)注釋:轉換一個字符串StartPos=countDoByteAry(count)=TmpByte(cou

34、nt-StartPos)count=count+1IfByteAry(count-1)=0ThenExitDoLoop注釋:將每一個字符串對應的字節(jié)數(shù)組按順序填入結果數(shù)組中ReDimPreserveByteAry(count-1)NextiEndSub下面看一個轉換的例子:DimResultAry()asByteDimSomeStr(2)asStringSomeStr(0)=測試1SomeStr(1)=測試222SomeStr(2)=測試33CallChangeStrAryToByte(SomeStr,ResultAry)注釋:轉換字符串數(shù)組當轉換完成以后,查看字節(jié)數(shù)組ResultAry,其中

35、包含了21個元素,依次是:178,226,202,212,49,0,178,226,202,212,50,50,50,0,178,226,202,212,51,51,0。其中,178,226是測的字節(jié)碼,202,112是試的字節(jié)碼,49,50,51分別為字符1、2、3的ASCII碼。可見,經(jīng)過轉換后,字符串數(shù)組中的各個元素按順序放在了字節(jié)數(shù)組中,相互間以終止符0分隔。這樣,字符串數(shù)組就全部轉換成了字節(jié)數(shù)組,然后只要將字節(jié)數(shù)組的第一個元素以傳址的方式傳入動態(tài)連接庫,DLL過程就可以正確地訪問數(shù)組中的所有字符串了。但是,使用這種方法,當DLL過程處理結束返回VB時,VB得到的仍然是字節(jié)數(shù)組。如果需

36、要在VB中再次得到該字節(jié)數(shù)組表示的字符串,還要把整個字節(jié)數(shù)組重新以0為分割符分成多個子數(shù)組(每個子數(shù)組都對應原來字符串數(shù)組中的一個元素),然后使用VB函數(shù)StrConv將每個子數(shù)組轉換成字符串(轉換時第二個參數(shù)選vbUnicode),就可以顯示或進行其它操作了。例如,其中一個子數(shù)組的名字是SubAry,則函數(shù)StrConv(SubAry,vbUnicode)就返回了它所對應的字符串??傊?,VB應用程序和動態(tài)庫間字符串參數(shù)的傳遞是一個比較復雜的過程,使用時要非常謹慎。同時應盡可能避免傳遞字符串數(shù)組類型的參數(shù),因為這很容易引起下標越界、堆棧溢出等嚴重錯誤。(3)、用戶自定義類型(User-defi

37、nedType)參數(shù)的傳遞用戶自定義類型在VB中是一種重要的數(shù)據(jù)類型,它為編程者提供了很大的靈活性,使開發(fā)人員可以根據(jù)需要構造自己的數(shù)據(jù)結構。它相當于C/C+中的結構類型(structure)。在VB中,允許程序員以傳址的方式將自定義數(shù)據(jù)類型參數(shù)傳入動態(tài)庫,DLL過程也可以將修改后的參數(shù)返回VB程序。但是,在VB中仍然不支持以傳值的方式傳遞用戶自定義類型參數(shù)。傳遞用戶自定義類型參數(shù)時,必須確保VB中的數(shù)據(jù)類型的成員與動態(tài)庫中的結構成員是一一對應的,所占空間也必須嚴格一致。這里所說的一一對應,不僅是指VB中的所有結構成員在動態(tài)庫的結構中都必須有對應的元素,而且它們在數(shù)據(jù)結構中定義的順序也必須嚴格一致,這是VB中使用的數(shù)據(jù)結構成員對齊方式?jīng)Q定的

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論