使用VC编写VB使用DLL
使用VC編寫VB使用DLL
一、在函數定義前必須加上extern "c",_stdcall關鍵字。
?extern "C" int _stdcall Sum(int x,int y)
?{
??return x+y;
?}
?
二、DLL的.def文件中必須加上入口函數
??? EXPORTS
???? sample @1
????
?sample是你要在VB中調用的函數名,@1表示該函數在DLL中的編號
?
三、要注意DLL中的函數和VB中的函數聲明在名稱、返回類型、參數類型、參數個數等方面必須完全相同,尤其要注意大小寫的問題。
注意事項:
?1、必須保證VB和VC的參數個數相同,參數所占字節數也一致
3.數組參數在DLL中的傳遞
由于DLL經常用來進行一些底層的運算操作,因此應用程序常需要傳遞大量的數據給DLL。在C++中,指針是進行數組操作的最佳選擇,但VB中沒有指針的概念。這通常可用兩種方法來解決。
其一,在VB中聲明DLL時,用byref來代替byval,即可將數組指針傳遞給DLL。
另外,將數組聲明為變體型(variant),即可直接將數組傳遞給DLL。
四、在vb中聲明("dllTest.dll" 使用的是相對路徑,你可以將dll.dll放到.exe所在的目錄或系統目錄),函數名大小敏感
Private Declare Function Sum Lib "dllTest.dll" (ByVal x As Long, ByVal y As Long) As Long
五、例子
?1、新建一個win32 dynamic library,空的工程
?2、新建一個dllTest.cpp 文件,并添加到工程。內容如下
// dll4.cpp : Defines the entry point for the DLL application.
//#include "stdafx.h"BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{return TRUE;
}extern "C" int _stdcall Sum(int x,int y)
{return x+y;
}
extern "C" int _stdcall GetNum(int Num) /*具體實現*/
{ return Num;
}
?// dll4.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
BOOL APIENTRY DllMain( HANDLE hModule,
?????????????????????? DWORD? ul_reason_for_call,
?????????????????????? LPVOID lpReserved
????? )
{
??? return TRUE;
}
extern "C" int _stdcall Sum(int x,int y)
{
?return x+y;
}
extern "C" int _stdcall GetNum(int Num)????? /*具體實現*/
{
?return Num;????
}
?3,新建一個dllTest.def文件,并添加到工程。內容如下:
?EXPORTS???
?????? ? Sum @1?
?
?
?相關知識點:
?
?1)? 函數調用約定(Calling Convention)
??
?c++編譯器
?
??? 編譯器的命令行參數是/Gz,__stdcall是Pascal程序的缺省調用方式,大多數Windows的API也是__stdcall調用約定。__stdcall函數調用約定將函數參數從右向左入棧,除非使用指針或引用類型的參數,所有參數采用傳值方式傳遞,由被調用函數負責清除棧中的參數。對于C函數,__stdcall的名稱修飾方式是在函數名字前添加下劃線,在函數名字后添加@和函數參數的大小,例如:_functionname@number
?函數名字修飾(Decorated Name)方式
??? 函數的名字修飾(Decorated Name)就是編譯器在編譯期間創建的一個字符串,用來指明函數的定義或原型。LINK程序或其他工具有時需要指定函數的名字修飾來定位函數的正確位置。多數情況下程序員并不需要知道函數的名字修飾,LINK程序或其他工具會自動區分他們。當然,在某些情況下需要指定函數的名字修飾,例如在C++程序中,為了讓LINK程序或其他工具能夠匹配到正確的函數名字,就必須為重載函數和一些特殊的函數(如構造函數和析構函數)指定名字裝飾。另一種需要指定函數的名字修飾的情況是在匯編程序中調用C或C++的函數。如果函數名字,調用約定,返回值類型或函數參數有任何改變,原來的名字修飾就不再有效,必須指定新的名字修飾。C和C++程序的函數在內部使用不同的名字修飾方式,下面將分別介紹這兩種方式。
1. C編譯器的函數名修飾規則
??? 對于__stdcall調用約定,編譯器和鏈接器會在輸出函數名前加上一個下劃線前綴,函數名后面加上一個“@”符號和其參數的字節數,例如_functionname@number。__cdecl調用約定僅在輸出函數名前加上一個下劃線前綴,例如_functionname。__fastcall調用約定在輸出函數名前加上一個“@”符號,后面也是一個“@”符號和其參數的字節數,例如@functionname@number。???
?
2. C++編譯器的函數名修飾規則
??? C++的函數名修飾規則有些復雜,但是信息更充分,通過分析修飾名不僅能夠知道函數的調用方式,返回值類型,參數個數甚至參數類型。不管__cdecl,__fastcall還是__stdcall調用方式,函數修飾都是以一個“?”開始,后面緊跟函數的名字,再后面是參數表的開始標識和按照參數類型代號拼出的參數表。對于__stdcall方式,參數表的開始標識是“@@YG”,對于__cdecl方式則是“@@YA”,對于__fastcall方式則是“@@YI”。參數表的拼寫代號如下所示:
X--void???
D--char???
E--unsigned char???
F--short???
H--int???
I--unsigned int???
J--long???
K--unsigned long(DWORD)
M--float???
N--double???
_N--bool
U--struct
....
指針的方式有些特別,用PA表示指針,用PB表示const類型的指針。后面的代號表明指針類型,如果相同類型的指針連續出現,以“0”代替,一個“0”代表一次重復。U表示結構類型,通常后跟結構體的類型名,用“@@”表示結構類型名的結束。函數的返回值不作特殊處理,它的描述方式和函數參數一樣,緊跟著參數表的開始標志,也就是說,函數參數表的第一項實際上是表示函數的返回值類型。參數表后以“@Z”標識整個名字的結束,如果該函數無參數,則以“Z”標識結束。下面舉兩個例子,假如有以下函數聲明:
int Function1(char *var1,unsigned long);
其函數修飾名為“?Function1@@YGHPADK@Z”,而對于函數聲明:
void Function2();
?其函數修飾名則為“?Function2@@YGXXZ” 。
?
??? 對于C++的類成員函數(其調用方式是thiscall),函數的名字修飾與非成員的C++函數稍有不同,首先就是在函數名字和參數表之間插入以“@”字符引導的類名;其次是參數表的開始標識不同,公有(public)成員函數的標識是“@@QAE”,保護(protected)成員函數的標識是“@@IAE”,私有(private)成員函數的標識是“@@AAE”,如果函數聲明使用了const關鍵字,則相應的標識應分別為“@@QBE”,“@@IBE”和“@@ABE”。如果參數類型是類實例的引用,則使用“AAV1”,對于const類型的引用,則使用“ABV1”。下面就以類CTest為例說明C++成員函數的名字修飾規則:
class CTest
{
......
private:
??? void Function(int);
protected:
??? void CopyInfo(const CTest &src);
public:
??? long DrawText(HDC hdc, long pos, const TCHAR* text, RGBQUAD color, BYTE bUnder, bool bSet);
??? long InsightClass(DWORD dwClass) const;
......
};
?
?
總結
以上是生活随笔為你收集整理的使用VC编写VB使用DLL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我写的一个给time_t赋值的小函数
- 下一篇: vc6.0快捷键大全- -