CString aaa="hello" strcpy(s, (LPSTR)(LPCTSTR)aaa); } 在VB中 Private Declare Function Test2 Lib "aaaa.dll" (ByVal buffer As String) As Long Dim aaaaa As String * 255Private Sub Command1_Click() Test2 (aaaaa) MsgBox aaaaa, 48, "TEST"End Sub
int a ByVal a as long Call func(…,a,…) long a ByRef a as long Call func(…,byval a,…) int *pa ByRef pa as long Call func(…,pa,…) long *pa ByVal pa as long Call func(…,varptr(pa),…) *(1) char *pstr ByVal pstr as string Call func(…,pstr,…) *(2) wchar *pstr ByRef pstr as string Call func(…,byval pstr,…) struct tagX *p ByRef p as tagX Call func(…,ptag,…) *(3) HANDLE h ByVal h as long Call func(…,h,…) *(4) 注意 1)不推荐使用此方式2)如果DLL要求一个字符串缓冲区,一定要在调用前初始化字串,即dim t as string * 503)用户定义子类型必须用ByRef方式传递, 4)任何内核对象的句柄(process, thread, module, file, filemapping, semaphore等)和大多数GDI对象的句柄都能用此方式传递。
To bluesky_ql(茄子) : 在.def中加入 Test2@1
字串参数凡是所有字串参数指标都以 ByVal 参数名称 As String 传。如RegOpenKeyEx()的第二参数 ByVal lpSubKey As String,便是一例。或许会问,这个例子是把subkey值传给 Win API所以用ByVal,没什麽大不了,其实不然,要Win API传回字串时,也一定要用ByVal的宣告。这是VB5字串格式(BSTR)与WIN API标准字串格式(LPSTR)不同的因素。LPSTR 字串格式是NULL Terminate的字串,若有一字串"HaHa !OK!",则格式如下: ----------------------------------------------------------------------------- Address 0 1 2 3 4 5 6 7 8 9 -- -- -- -- -- -- -- -- -- -- 内容 H a H a ! O K ! \0而BSTR则在字串的前面还有一个LONG值存字串长度,格式如下:Address 0.. 3 4 5 6 7 8 9 10 11 12 13 ------ -- -- -- -- -- -- -- -- -- -- 内容 9 H a H a ! O K ! \0 -----------------------------------------------------------------------------所以了字串以ByVal的方式来传像不像指到BSTR中第4个位置,如此一来,不就和LPSTR 可以相容了吗?我想也正因为如此以ByVal的方式来传String可以取得Win API的传回值,(就算不是如此,至少这麽想比较记得住String要用ByVal的方式传)。现在又有一个问题,Window95 API的字串使用的是ASCII Code但VB是用Unicode,Unicode占两个位元组,那麽能和WinAPI的字串相?所幸我们可以先不用管它,因为vb本身做了转换,即vb传给api时,转了一次,传回时又转回 Unicode,所以如果我们用的是Byte Array来传字串,也可以但是要自己去转码。。然而32位元的VB 中,字串有种格式,一个是BSTR,另一个是HLSTR,如果我们宣告的串是非固定长度者,就会是BSTR,反之则为HLSTR。DIM BSTR5 AS STRING BSTR DIM HLSTR5 AS STRING(255) HLSTRVB5中WIN32 API的呼叫请多多使用BSTR,因为使用HLSTR的结果是,VB还得做HLSTR-> BSTR的转换来呼叫WIN API若有传回STRING而後再做BSTR->HLSTR的工作。然而使用BSTR来工作时,若处理有传回值的STRING参数,则还要有额外的动作:1.先给定字串的初值,且字串的长度要够放传回值。 2.传回後,去除传回值中多余的字元。或 例如: ----------------------------------------------------------------------------- int GetWindowText( HWND hWnd, // handle of window or control with text LPTSTR lpString, // address of buffer for text int nMaxCount // maximum number of characters to copy ); 该 API 取得WINDOW Title Bar的文字,而传回值是放入lpString的character个数。 VB的宣告如下:Decl are Function GetWindowText Lib "user32" Alias "GetWindowTextA" _ (ByVal hwnd As Long, _ ByVal lpString As String, _ ByVal cch As Long) As Long 范例一 ***************************************************************************** Dim CharCnt As Long Dim lpString As String Dim tmpstr As String Dim NullPos As LongForm1.Caption = "这是一个test" lpString = String(255, 0) '设定初值 CharCnt = GetWindowText(Me.hwnd, lpString, 256) 'CharCnt = 12 tmpstr = Left(lpString, CharCnt) '如此做会有一些问题 Debug.Print Len(tmpstr) '得12 Label1.Caption = Left(lpString, CharCnt) Debug.Print Len(Label1.Caption) '得8 *****************************************************************************以范例一的例子来看,设定lpString= String(255,0)的目的,是设定255个字元的空间给 lpString(加上最後的null一共256),CharCnt的值是12,明眼者可看到len("这是一个test") 会是8,但CharCnt是12, 所以直接使用Left()函数来取得子字串会有问题,这是UniCode与ANSI String间的关系,所以了,当您看到有些书的范例用这种方法取子字串,是不太完善的,所以改用范例二的方式,比较正确。范例二 ***************************************************************************** Form1.Caption = "这是一个test" lpString = String(255, 0) '设定初值 CharCnt = GetWindowText(Me.hwnd, lpString, 256) 'CharCnt = 12 NullPos = InStr(1, lpString, Chr(0), vbBinaryCompare) tmpstr = Left(lpString, NullPos - 1) lable1.Caption = tmpstr *****************************************************************************
我举个例子吧 extern "C" __declspec(dllexport) bool __stdcall SMSSendMessage(LPSTR csTelNumber,LPSTR csMessage ) { if(!theApp.m_bSendSucess) return false; bool nResult=(bool)theApp.m_send.SendMessage(csTelNumber,csMessage); return nResult; } 注意:LPSTR不能写为CString类型的 在VB中这样:Declare Function mymessage Lib "你的生成的.dll" Alias "SMSSendMessage" (ByVal aa As String, ByVal bb As String) As Integer
呵呵,也遇到可能要在VB里用MFC开发的dll
如果是COM,那肯定是BSTR了,用VARIANT也可以,但是麻烦
nnd 这几天我写dll给 delphi用 靠 想来想去 就写 win32 的 好了基于 静态连接mfc的regular dll好久都没搞定 郁闷
{
CString aaa="hello"
strcpy(s, (LPSTR)(LPCTSTR)aaa);
}
在VB中
Private Declare Function Test2 Lib "aaaa.dll" (ByVal buffer As String) As Long
Dim aaaaa As String * 255Private Sub Command1_Click() Test2 (aaaaa)
MsgBox aaaaa, 48, "TEST"End Sub
然后在dll函数内部用CString 我觉得只要参数用基本类型传入传出 应该没问题的
我晚上试试
如果改成char*,则用用ByVal String
关键字 none
首先必须了解此函数在C中的原型,包括参数类型和传递方式。C DLL 原型 VB声明 VB调用
int a ByVal a as long Call func(…,a,…)
long a ByRef a as long Call func(…,byval a,…)
int *pa ByRef pa as long Call func(…,pa,…)
long *pa ByVal pa as long Call func(…,varptr(pa),…) *(1)
char *pstr ByVal pstr as string Call func(…,pstr,…) *(2)
wchar *pstr ByRef pstr as string Call func(…,byval pstr,…)
struct tagX *p ByRef p as tagX Call func(…,ptag,…) *(3)
HANDLE h ByVal h as long Call func(…,h,…) *(4) 注意 1)不推荐使用此方式2)如果DLL要求一个字符串缓冲区,一定要在调用前初始化字串,即dim t as string * 503)用户定义子类型必须用ByRef方式传递, 4)任何内核对象的句柄(process, thread, module, file, filemapping, semaphore等)和大多数GDI对象的句柄都能用此方式传递。
在.def中加入
Test2@1
-----------------------------------------------------------------------------
Address 0 1 2 3 4 5 6 7 8 9
-- -- -- -- -- -- -- -- -- --
内容 H a H a ! O K ! \0而BSTR则在字串的前面还有一个LONG值存字串长度,格式如下:Address 0.. 3 4 5 6 7 8 9 10 11 12 13
------ -- -- -- -- -- -- -- -- -- --
内容 9 H a H a ! O K ! \0
-----------------------------------------------------------------------------所以了字串以ByVal的方式来传像不像指到BSTR中第4个位置,如此一来,不就和LPSTR 可以相容了吗?我想也正因为如此以ByVal的方式来传String可以取得Win API的传回值,(就算不是如此,至少这麽想比较记得住String要用ByVal的方式传)。现在又有一个问题,Window95 API的字串使用的是ASCII Code但VB是用Unicode,Unicode占两个位元组,那麽能和WinAPI的字串相?所幸我们可以先不用管它,因为vb本身做了转换,即vb传给api时,转了一次,传回时又转回 Unicode,所以如果我们用的是Byte Array来传字串,也可以但是要自己去转码。。然而32位元的VB 中,字串有种格式,一个是BSTR,另一个是HLSTR,如果我们宣告的串是非固定长度者,就会是BSTR,反之则为HLSTR。DIM BSTR5 AS STRING BSTR
DIM HLSTR5 AS STRING(255) HLSTRVB5中WIN32 API的呼叫请多多使用BSTR,因为使用HLSTR的结果是,VB还得做HLSTR-> BSTR的转换来呼叫WIN API若有传回STRING而後再做BSTR->HLSTR的工作。然而使用BSTR来工作时,若处理有传回值的STRING参数,则还要有额外的动作:1.先给定字串的初值,且字串的长度要够放传回值。
2.传回後,去除传回值中多余的字元。或
例如:
-----------------------------------------------------------------------------
int GetWindowText(
HWND hWnd, // handle of window or control with text
LPTSTR lpString, // address of buffer for text
int nMaxCount // maximum number of characters to copy
);
该 API 取得WINDOW Title Bar的文字,而传回值是放入lpString的character个数。
VB的宣告如下:Decl are Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, _
ByVal lpString As String, _
ByVal cch As Long) As Long
范例一
*****************************************************************************
Dim CharCnt As Long
Dim lpString As String
Dim tmpstr As String
Dim NullPos As LongForm1.Caption = "这是一个test"
lpString = String(255, 0) '设定初值
CharCnt = GetWindowText(Me.hwnd, lpString, 256) 'CharCnt = 12
tmpstr = Left(lpString, CharCnt) '如此做会有一些问题
Debug.Print Len(tmpstr) '得12
Label1.Caption = Left(lpString, CharCnt)
Debug.Print Len(Label1.Caption) '得8
*****************************************************************************以范例一的例子来看,设定lpString= String(255,0)的目的,是设定255个字元的空间给 lpString(加上最後的null一共256),CharCnt的值是12,明眼者可看到len("这是一个test") 会是8,但CharCnt是12, 所以直接使用Left()函数来取得子字串会有问题,这是UniCode与ANSI String间的关系,所以了,当您看到有些书的范例用这种方法取子字串,是不太完善的,所以改用范例二的方式,比较正确。范例二
*****************************************************************************
Form1.Caption = "这是一个test"
lpString = String(255, 0) '设定初值
CharCnt = GetWindowText(Me.hwnd, lpString, 256) 'CharCnt = 12
NullPos = InStr(1, lpString, Chr(0), vbBinaryCompare)
tmpstr = Left(lpString, NullPos - 1)
lable1.Caption = tmpstr
*****************************************************************************
extern "C" __declspec(dllexport) bool __stdcall SMSSendMessage(LPSTR csTelNumber,LPSTR csMessage )
{
if(!theApp.m_bSendSucess) return false;
bool nResult=(bool)theApp.m_send.SendMessage(csTelNumber,csMessage);
return nResult;
}
注意:LPSTR不能写为CString类型的
在VB中这样:Declare Function mymessage Lib "你的生成的.dll" Alias "SMSSendMessage" (ByVal aa As String, ByVal bb As String) As Integer
用VC的MFC写的DLL不能导出VB使用的类和控件,导出可供VB使用的类可使用Win32 DLL,可以在标准DLL中导出VB可使用的函数,函数体内可使用MFC,但函数的参数必须使用和VB匹配的数据类型。
欢迎指正和补充!