VB标准DLL问题多多,求大佬们指点
最近因为需要将VB程序中的功能做成DLL给其它语言使用,就开始做DLL,但测试时发现很多问题:一、不能将string转换成integer。
二、数组做为参数也不行
只有直接将string为参数,不进行转换,输出string可以,但有问题,原型如下:
Public Function fncStr(ByVal str As String) As String
fncStr = str & "fncStr"
End Function
最后输出的只能是输入字串加上一个f,而不是加上fncStr
三、可以进行加减运算,但不能进行乘方。
另,做标准DLL的方法如下:建立Active DLL工程,新加一个Moudble,将输出函数写入,截获编译过程中的OBJ,再用DEF文件形式定义输出函数,再在Link命令行中加上相应参数,其中输出函数内容如下:
LIBRARY Project1
EXPORTS
DllMain @1
fncStr @2
fncInt @3
fncStrtoInt @4
fncVarArry @5
fncOutInt @6
Decrement @7
Square @8
Public Function fncStr(ByVal str As String) As String
fncStr = str & "fncStr"
End Function
Public Function fncInt(ByVal a As Integer, ByVal b As Integer) As Integer
fncInt = a + b
End Function
Public Function fncStrtoInt(ByRef str As String) As Integer
Dim a As String
a = str
fncStrtoInt = Val(a)
End Function
Public Function fncVarArry(ByRef str() As Integer) As Integer
ReDim str(5)
fncVarArry = str(1)
End Function
Public Function fncOutInt() As Integer
Dim a As String
a = "123"
fncOutInt = Val(a)
End Function
Public Function Decrement(var As Integer) As Integer
If Not IsNumeric(var) Then Err.Raise 5
Decrement = var - 1
End Function
Public Function Square(var As Long) As Long
If Not IsNumeric(var) Then Err.Raise 5
Square = var ^ 2
End Function
上面有这几个功能,只有fncStr和fncInt可以执行,但fncStr执行结果不正确。
无论怎么测试,甚至对字串进行了Uncode,都直接报错,连VB自己都无法调用自己写的DLL
网上的做标准DLL的方法,都是简单的用个加法什么的做例子,确实没错,但复杂一点的就象我做的这个DLL,就不行,不知道为什么,急求高手指点!!
不会用C,所以没办法。 dll vb 字符串可以存储在Byte类型的数组中。再传给调用的程序。
除了加法可以直接简单机器码实现,其他都需要通过 VB 运行库实现。
Option Explicit
Dim strP As String
Dim bytA() As Byte
'转化为Byte类型的数组
Private Sub Command1_Click()
Dim intP As Integer
bytA = StrConv(strP, vbUnicode)
For intP = LBound(bytA) To UBound(bytA)
Debug.Print bytA(intP)
Next intP
End Sub
'转化为字符串
Private Sub Command2_Click()
Dim strT As String
strT = StrConv(bytA, vbFromUnicode)
Debug.Print strT
End Sub
Private Sub Form_Load()
strP = "中华人民共和国"
End Sub
你试试先调用一下 DllMain 进行初始化。
VB6根本就不能做什么标准“dll”,要是能做,微软早做进去了,那还能多卖点钱。不要以为上网搜了几篇糊弄菜鸟的文章,知道一个骗骗链接器的偏方就挽起袖子大干一场。 别的语言应该支持COM调用吧?直接按COM组件的方式提供接口.
如果非要以API的方式提供接口,那么在字符串的处理方面就不能以常规的方式来调用,需要做很多工作.
我论坛这里6楼有个参考:
http://www.m5home.com/bbs/thread-1698-1-1.html 非常感谢楼上朋友的回答,不过还是没有解决问题,郁闷啊,难道真的不能生成标准DLL?
现在的主要问题是数组不能传入,字符串不能在DLL内部进行转换,可能和VB使用的函数有关吧,必须使用API的可能才行,现在采用传址和内存拷贝的方式倒是可以传进数组,但只有VB能使用,用DELPHI则报内存错误,DLL实现如下:
Public Function fncarray(ByVal lp As Long) As Long
Dim a(0 To 5) As Long
CopyMemory a(0), ByVal lp, 4
fncarray = a(0)
End Function
VB调用如下:(采用的是传址)
Long
Declare Function fncarray Lib "D:\delpitest\VBDll\DelphiTest\vbdll.dll" (lp As Long) As Long
str(0) = 134
str(1) = 2
b = fncarray(str(0))
MsgBox b
而DELPHI调用只能用一种方式传址,调用时报内存错误:
第一种:
function fncarray(var lp:array of longint):longint;stdcall; external 'vbdll.DLL';procedure TForm1.Button4Click(Sender: TObject);
var
Arg1:array[0..6] of longint;//OleVariant;
begin
//rg1 := VarArrayCreate([0,5],varsmallint);
Arg1[0] :=123;
Arg1[1] :=2;
fncarray(Arg1) ;
end;
菜鸟,没办法,瞎想瞎干,求高手指点一下到底怎么解决
用VB和DELPHI同时测试一下四楼朋友的办法,开始测试 应该是 Delphi 中声明错了吧。
如果我没记错的话,Delphi 中的 array of 参数包括了数据的首指针和数据的长度两个信息,这和 VB 函数只有一个指针不匹配。 四楼朋友的,不能在DELPHI中通过,看来,是和使用VB内部函数有相当的关系,数组,很可能也不能使用。只好再试啊试。都试了好几天了,看了代码都恶心。
回七楼朋友,声明没有错误,DELPHI只能这样声明才能传址,否则编译不通过 Delphi 应该支持 COM 吧。
首选应该是 COM 调用,语言不支持才会考虑标准接口。
理论上,任何一种语言只要能调用“标准dll”,就可以支持com。因为整个com其实也就是一组“标准dll”,只不过附加了很多约定的调用规范和数据类型。
(根据《BORLAND传奇》李维著介绍)在早期,微软为了防止对手竞争,曾经对于OLE Server(可以认为是ActiveX Control的前身)的实现遮遮掩掩,导致Delphi和其它非MS厂商的开发工具在实现OLE Server的时候存在一些微妙的问题。
不过后来微软放开了这些技术标准。
而且,对于COM的调用,则是被研究烂透的技术。国内有无数人在搞它。甚至连国内山寨的“易语言”都可以完美调用COM接口。所以,一种语言如果声称能调用DLL,却不能调用COM,只能说这种语言太烂,它的社区都没有人愿意去做这样一件本来都不难做的事情。 还是拿点精力解决DLL了,没办法,要求用标准DLL
脚本类的也能调用COM,但不一定能调用标准dll了
写标准dll还是用C C++ delphi什么的写吧,VB不是干这个的料。
嗯。我可没有反过来说。 老大们,还是说说VB做DLL的问题好不?都把楼主的事忘了 之前说过了啊,在调用方面需要有约定,不能像普通的DLL那样调用. 还想这些问题,会VC++不,推荐使用VC++。
VB是可以做这样的标准DLL的,但你要对VB较精通,要深层了解VB.
这个是我的VB标准DLL,都可以显示对话框,串处理更是没有问题
http://download.csdn.net/detail/taoguangye/3913144 其实哪有什么标准dll和com dll 之分...
都是标准dll
只不过是一种特殊应用而已, 利用约定好的标准调用, 也仅此而已...
建议使用 VC++ 来做,非常简单。
VB的数据类型和其他语言有一些区别。
要达到vb数据传到dll,vb的帮助里面说了很多。
同样的,要从其他语言传数据到vb写的dll里面,一样有很多限制。
如果你对vb的数据在内存的组织形式非常了解,应该可以解决。
所以比较笨的办法就是在调试器里面调试用户程序和vb dll程序,看看对应关系是否正确。
如果对应关系不正确,就需要在用户程序里面额外写很多程序,当然,接口会很不友好。 这些用 VB来做,也非常简单。
不能正确运行,只能说明楼主还不会处理这些问题。
用我的那个 DLL制作工具,测试全部通过:
DLL代码如下(可以用我那个DLL模板):
' * * * ---== VB6.0 StandardCall DLL 模板 ==--- * * *
Option Explicit
' 在这后面写上你所需要的数据类型、变量、常量、API等声明
' - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Private Sub Main(): End Sub ' 请不要修改或删除这一行!!!
' - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
' * * * DllMain 名称不能改!如果要在其它编程环境中 * * *
' * * * 用LoadLibrary( )使用导出函数,就加上此函。 * * *
' Function DllMain(ByVal hInstDLL As Long, _
' ByVal fdwReason As Long, _
' ByVal lpwReserved As Long) As Long
' 'Select Case fdwReason
' '' 这4个参数的详情,查阅 MSDN 或 百度 。
' ' Case DLL_PROCESS_ATTACH: ' 第一次被映射到进程的地址空间时
' ' Case DLL_PROCESS_DETACH: ' 从进程的地址空间被解除映射时
' ' Case DLL_THREAD_ATTACH: ' 进程中每次建立线程,都会调用这个参数
' ' Case DLL_THREAD_DETACH: ' 线程函数返回或调用了ExitThread来结束线程时
' 'End Select
' DllMain = 1 ' 返回参数
' End Function
' - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
'在这后面写上你的其它 Sub/Function ,或者全部写到其它模块中
Private Function fncStr(ByVal str As String) As String
fncStr = StrConv(StrConv(str, vbUnicode) & "fncStr", vbFromUnicode)
End Function
Private Function fncInt(ByVal a As Integer, ByVal b As Integer) As Integer
fncInt = a + b
End Function
Private Function fncStrToInt(ByVal str As String) As Integer
fncStrToInt = Val(StrConv(str, vbUnicode))
End Function
Private Function fncVarArry(ByRef str() As Integer) As Integer
ReDim str(5)
fncVarArry = str(1) ' 被重定义了,返回为0
End Function
Private Function fncVarArry2(ByRef str() As Integer) As Integer
fncVarArry2 = str(3) ' 返回下标为3的元素的值
End Function
Private Function fncOutInt() As Integer
Dim a As String
a = "123"
fncOutInt = Val(a)
End Function
Private Function Decrement(var As Integer) As Integer
' 下面这句 If 是多余的。当然有这个也能正常运行。
'If Not IsNumeric(var) Then Err.Raise 5
Decrement = var - 1
End Function
Private Function Square(var As Long) As Long
' 下面这句 If 是多余的。当然有这个也能正常运行。
'If Not IsNumeric(var) Then Err.Raise 5
Square = var ^ 2
End Function
EXE测试工程代码如下:
Option Explicit
'private Function fncStr(ByVal str As String) As String
Private Declare Function fncStr Lib "TestDll" (ByVal sText As String) As String
'private Function fncInt(ByVal a As Integer, ByVal b As Integer) As Integer
Private Declare Function fncInt Lib "TestDll" (ByVal a As Integer, ByVal b As Integer) As Integer
'private Function fncStrToInt(ByRef str As String) As Integer
Private Declare Function fncStrToInt Lib "TestDll" (ByVal sNum As String) As Integer
'private Function fncVarArry(ByRef str() As Integer) As Integer
Private Declare Function fncVarArry Lib "TestDll" (ByRef str() As Integer) As Integer
Private Declare Function fncVarArry2 Lib "TestDll" (ByRef str() As Integer) As Integer
'private Function fncOutInt() As Integer
Private Declare Function fncOutInt Lib "TestDll" () As Integer
'private Function Decrement(var As Integer) As Integer
Private Declare Function Decrement Lib "TestDll" (var As Integer) As Integer
'private Function Square(var As Long) As Long
Private Declare Function Square Lib "TestDll" (var As Long) As Long
Private Sub Command1_Click()
Dim tArr() As Integer
Dim i As Long
ReDim tArr(7)
Call Randomize
For i = 0 To 7
tArr(i) = Rnd() * 100 + 6
Print i; tArr(i)
Next
Print " ----------"
Print "fncStr "; fncStr("Test string + ")
Print "fncInt "; fncInt(4, 8)
Print "fncStrToInt "; fncStrToInt("123")
' 返回值为 tAtt(3)
Print "fncVarArry2 "; fncVarArry2(tArr)
' 由于在函数内重新定义数组,返回值为0
Print "fncVarArry "; fncVarArry(tArr)
Print "fncOutInt "; fncOutInt()
Print "Decrement "; Decrement(6)
Print "Square "; Square(3)
End Sub
在 EXE工程代码,在IDE模式、在编译后,都可以正确运行!
DLL的代码是从楼主那儿复制的。
只作了少量修正。 VB不支持其他语言(如VC)的数组形式。
我试过用VC传递数组指针到VB,VB无法读取,甚至VB用API函数CopyMemory来复制也不行。
你弄明白应该如何去 CopyMemory 没……
你清楚如果“传递数组指针”,在VB6中应该如何写代码不!!!
此言差矣.
补充:VB , COM/DCOM/COM+