vb6.0调用dll文件,dll文件中有多个函数

zzz615134 2017-08-03 11:27:25
现在想用vb6.0调用一个别的公司给的动态链接库dll文件,该公司之前用过c++调用,但没用过vb。在c++里面不是要调lib文件、h文件吗。但是我看网上说vb不能调用这两个文件,所以就不知道该怎么办了。
网上调用dll的例子都是一个dll为一个函数,但是我这个里面有多个函数,请问该如何调用?
...全文
672 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2017-08-07
  • 打赏
  • 举报
回复
不要做A语言代码修改为B语言代码的无用功。 也不要做用A语言代码直接调用B语言代码库这样复杂、这样容易出错的傻事。 只需让A、B语言代码的输入输出重定向到文本文件,或修改A、B语言代码让其通过文本文件输入输出。 即可很方便地让A、B两种语言之间协调工作。 比如: A将请求数据写到文件a.txt,写完后改名为aa.txt B发现aa.txt存在时,读取其内容,调用相应功能,将结果写到文件b.txt,写完后删除aa.txt,再将b.txt改名为bb.txt A发现bb.txt存在时,读取其内容,读完后删除bb.txt 以上A可以替换为任何一种开发语言或开发环境,B可以替换为任何一种与A不同的开发语言或开发环境。 除非A或B不支持判断文件是否存在、文件读写和文件更名。 但是谁又能举出不支持判断文件是否存在、文件读写和文件更名的开发语言或开发环境呢? 可以将临时文件放在RamDisk上提高效率减少磨损磁盘。 数据的结构很复杂的话,文本文件的格式问题可参考json或xml 共享临时文本文件这种进程之间的通讯方法相比其它方法的优点有很多,下面仅列出我现在能想到的: ·进程之间松耦合 ·进程可在同一台机器上,也可跨机,跨操作系统,跨硬件平台,甚至跨国。 ·方便调试和监视,只需让第三方或人工查看该临时文本文件即可。 ·方便在线开关服务,只需删除或创建该临时文本文件即可。 ·方便实现分布式和负载均衡。 ·方便队列化提供服务,而且几乎不可能发生队列满的情况(除非硬盘空间满) ·…… “跨语言、跨机,跨操作系统,跨硬件平台,跨国,跨*.*的”苦海无边, 回头是“使用共享纯文本文件进行信息交流”的岸!
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
DLL 调用约定错误 这个当然也不排“参数个数不一致导致堆栈不平衡”引起这个提示。 但是,你确定这个API一定是 stdcall的,而不是cdecl的? 还有,你最好还是把它的HW_INT64类型定义贴出来看看(包括相关的“前导定义‘) 因为如果它这个是用高版本VS平台编译的dll,应该是支持”64位整数“的, 它把64位整数ByVal压栈,象我那样把它拆成两个Long、ByVal传递,是不会有问题的。 当然你也可以再试一下,把ByVal llTaskID_Hig As Long去掉,这样只传一个32位整数给它,它会提示什么错误? 当然这样试时”连接操作不成功“不算错误。 我估计这样改了之后,仍然是会提示49错误的。 真是这样,也说明这个API是CDecl调用而不是stdcall调用。
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
引用 18 楼 Chen8013 的回复:
我在15楼的“调用示例”中写的那几个字符串,你要按你的“实际环境”写上对应的字符串。 我写在那儿的字符串,只是“表达一个意思”。
大侠现在提示错误49 bad dll calling convertion,调用约定是stdcall的没有问题。 还有一点我不明白是您把int64这一个参数拆成两个,这不就比dll中的函数形参个数多一个了吗,怎么一一对应,它怎么知道这两个参数是拼成那一个的?
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
我在15楼的“调用示例”中写的那几个字符串,你要按你的“实际环境”写上对应的字符串。 我写在那儿的字符串,只是“表达一个意思”。
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
从这些定义来看,我在15楼的API声明就没有错。 proc是“回调过程”,如果要进行回调处理,需要在标准模块中写一个相应的形式(参数要匹配)的过程,   把“过程地址”传给 procp 这个参数; 如果不需要这个参数就传0。
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
不管是什么“句柄”、指针,在VB6中基本上都是一律用 Long类型代替。 即使是“结构体指针”: 如果你不需要管它指向的数据,声明成Long类型,只管用Long变量接收、以及在它的那一套不同的API之间传递值; 如果需要“管数据”,那你必然要定义出相应的“结构体”(VB6中术语叫“用户类型数据”);    然后要定义相应类型的变量,    当“指针不为空”时,用Copymemory拷贝结构体对应长度的字节数到结构体变量中就行了。    当“指针为空”时,自然是操作失败,也不可拷贝数据。
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
这是HW_LPCSTR的定义

#ifndef _HW_CHAR_DEFINED
#define _HW_CHAR_DEFINED
typedef char HW_CHAR;
#endif // _HW_CHAR_DEFINED

#ifndef _HW_LPCSTR_DEFINED
#define _HW_LPCSTR_DEFINED
typedef const HW_CHAR* HW_LPCSTR;
#endif // _HW_LPCSTR_DEFINED
这是EZLINK_RECV_PROC的定义

#ifndef _EZLINK_RECV_PROC_DEFINED
#define _EZLINK_RECV_PROC_DEFINED
// void CALLBACK EZLinkRecvProc(HEZLINK hLink, HW_INT64 llTaskID, int iIndex, double dTime, const double* lpValue, bool bFinal, DWORD dwParam);
typedef void (CALLBACK* EZLINK_RECV_PROC)(HEZLINK hLink, HW_INT64 llTaskID, int iIndex, double dTime, const double* lpValue, bool bFinal, DWORD dwParam);
#endif // _EZLINK_RECV_PROC_DEFINED
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
好的,感谢大侠! 还有个问题就是我看它dll文件中有的变量声明为句柄,像这种的在vb中应该怎么声明。比如上面一直说的那个例子 函数类型为HEZLINK,文件说是句柄,连接失败时返回NULL。像这样的话该怎么声明。 这是HEZLINK的定义

typedef struct{} *HEZLINK;

EZLINK_API void EZLink_Disconnect(IN HEZLINK hLink)
像上面这个函数的参数以为这个类型,应该怎么声明
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
你自己要求对方提供使用的范例吧! 这个“崩溃问题”,我不可能再分析具体原因了。 即没测试的样本、也没测试的环境(需要连接“服务器”之类的,需要特定的网络环境吧!),   我不可能猜测出为什么会崩溃!
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
那恐怕只能说是那个dll的问题了。 一个比较“健壮”的代码,参数有问题,引起的问题是“操作失败”,而不是“造成进程崩溃”!
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
引用 28 楼 Chen8013 的回复:
最后一个参数,声明成Long类型,调用时传0啊!
还是一样的结果
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
最后一个参数,声明成Long类型,调用时传0啊!
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
是的,只不过最后一个参数您设的是long,我是string。不过我即便改成long还是一样的结果

Private Declare Function EZLink_Connect Lib "EasyLink.dll" ( _
                           ByVal lpszServerName As String, _
                           ByVal wServerPort As Integer, _
                           ByVal lpszuser As String, _
                           ByVal lpszPassword As String, _
                           ByVal llTaskID_Low As Long, _
                           ByVal llTaskID_Hig As Long, _
                           ByVal proc As Long, _
                           ByVal dwProcParam As Long, _
                           ByVal lpszLocalIP As String) As Long

舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
引用 24 楼 weixin_39587041 的回复:
现在运行之后直接成这个样子了,然后vb就关掉了。 我就是把那些string类型直接改成了赋字符串变量

m_hLink = EZLink_Connect(m_szServerIP, 3965, vbNullString, vbNullString, m_llTalkID.LowLong, m_llTalkID.HigLong, 0&, 0&, m_szLocalIP)

你这个调用方法,对应的API声明,是我在15楼写的那个吗???
舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
我在上面说的“把参数1分为2传递”,可能是不好理解,但实际是可行的! VB6中没有“64位整数”,但是Double类型是64位的数据,可以用这种类型的dll参数做个简单测试。 我写的DLL测试代码很简单,就是这样:
Option Explicit

' * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Private Sub Main():  End Sub '请不要修改或删除这一行!!!
' * * * * * * * * * * * * * * * * * * * * * * * * * * * *

Private Function DllMain(ByVal hModule As Long, _
                       ByVal ul_reason_for_call As Long, _
                       ByVal lpReserved As Long) As Long
   DllMain = 1
End Function

' 导出函数: 在函数中用消息显示接收到的参数值
Private Function TestCall(ByVal hWnd As Long, ByVal m As Double) As Long
   Call MessageBox(hWnd, m, "DLL 消息", 64&)
   TestCall = 0&
End Function
然后另外创建一个标准EXE工程,调用这个DLL的API进行测试。 其中主要的函数声明如下:
Private Declare Function TestA Lib "Test.dll" Alias "TestCall" ( _
                           ByVal hWnd As Long, ByVal v As Double) As Long
Private Declare Function TestB Lib "Test.dll" Alias "TestCall" ( _
                           ByVal hWnd As Long, _
                           ByVal pa As Long, ByVal pb As Long) As Long
对第二种声明形式的调用测试代码如下:
Private Sub Command2_Click()
   Dim w As LARGINT
   Dim v As Double

   v = Val(txtNum.Text)
   Call MsgBox("输入数据:" & vbLf & v, 64)
   Call MemCopy(8&, w, v)
   Call TestB(Me.hWnd, w.LowLong, w.HigLong)
End Sub
虽然上面 TestB 这个声明形式,跟“API参数原型”表面上看起来“完全是牛头不对马嘴”的!   不但参数个数不相符,而且类型也是完全不同的。 但是,事实证明,API中却是正确获取了传入的数据。 这个拆分传递的方法对于“Double参数”有效,对于INT64类型的参数其实照样有效! dll我已经编译好了,跟测试工程一起打包传到了我的百度网盘中。 楼主可以下载来看看,分享链接7天后失效。 链接: http://pan.baidu.com/s/1skZhqqT 密码: qc68
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
现在运行之后直接成这个样子了,然后vb就关掉了。 我就是把那些string类型直接改成了赋字符串变量

m_hLink = EZLink_Connect(m_szServerIP, 3965, vbNullString, vbNullString, m_llTalkID.LowLong, m_llTalkID.HigLong, 0&, 0&, m_szLocalIP)

舉杯邀明月 2017-08-06
  • 打赏
  • 举报
回复
引用 22 楼 weixin_39587041 的回复:
会不会还是我调用的时候哪一步有问题

    m_hLink = EZLink_Connect(ByVal StrPtr(m_szServerIP), 3965, vbNullString, vbNullString, m_llTalkID.HigLong, 0&, 0&, ByVal StrPtr(m_szLocalIP))

按你21楼的内容来看,我说的把INT64拆成两个Long参数才是正确的。 你这儿的调用,少了一个32位数据,肯定不可能正确调用。 并且,String参数传递不正确,ANSI编码格式的字符串,就应该声明成String类型,   调用API时直接给字符串变量或常量。 用 ByVal StrPtr( )是传递Unicode格式字符串用的,并且声明时还要把参数类型声明成Long才行。 以前听谁说过,用eXeScope可以查看dll的调用约定,但我一直没有看到过这个软件提供的“调用约定”信息。 如果我要看,那也只能是从反汇编代码来看。 VB6直接使用dll的导出函数,只能调用stdcall的。 其实也有办法在VB6中调用cdecl的函数:   这个需要“包装”一下,用“汇编代码 +CallWindowProc ”,绕个弯子来调用。 当然也可以用另外的支持cdecl调用的语言,重新“包装”一个dll,通过另一个dll来“中转一下”调用。
zzz615134 2017-08-06
  • 打赏
  • 举报
回复
会不会还是我调用的时候哪一步有问题

    m_hLink = EZLink_Connect(ByVal StrPtr(m_szServerIP), 3965, vbNullString, vbNullString, m_llTalkID.HigLong, 0&, 0&, ByVal StrPtr(m_szLocalIP))

zzz615134 2017-08-06
  • 打赏
  • 举报
回复
这是hw_int64的定义

#ifdef _MSC_VER
#ifndef _HW_UINT64_DEFINED
#define _HW_UINT64_DEFINED
typedef unsigned __int64 HW_UINT64;
#endif // _HW_UINT64_DEFINED

#ifndef _HW_INT64_DEFINED
#define _HW_INT64_DEFINED
typedef __int64 HW_INT64;
#endif // _HW_INT64_DEFINED
#endif // _MSC_VER
我试了只传32位的话还是提示错误49,但是我联系给我dll文件的人他说是用stdcall的 有什么方法可以检验这个是什么调用约定的吗?我看网上说如果不是stdcall的话需要做个封装dll,但感觉过程太复杂了,不会弄。。。。
舉杯邀明月 2017-08-05
  • 打赏
  • 举报
回复
引用 14 楼 weixin_39587041 的回复:
[quote=引用 13 楼 Chen8013 的回复:] 你既然把“char指针”声明为Long类型了,你再传字符串,当然不行啊!!! C++中的chat指针有几种,但最关键是要搞明白它用的是哪种字符编码! 我建议你先还是把那几个“char指针”的,声明成String类型来试,   大多数时候是ANSI格式编码的,声明成String类型,让VB6帮你去做那个细节工作。   传“空字符串”的地方,用vbNullString,不要用 "" 。 最后那个参数,还是声明成Long吧,调用时传0。 那个INT64的参数llTalkID :你用ByRef来传递,是不正确的!!!   C++中这儿是“传值”,你用ByRef传递肯定有问题啊。 我在11楼已经给你说了,“指针”才能用ByRef;“传值”你要把它这个参数拆成两个Long参数、并且是ByVale的!!!  注意调用时,前一个参数是“低段”,后一个参数是“高段”。
大神您能帮忙把我这个声明语句写一下吗?跪拜跪拜[/quote] 无语! 我已经给你说得很明白了,还不能理解? 自己好好测试一下啊 !!! 它那个 HW_LPCSTR 究竟应该是什么类型、在VB6中应该如何声明,得看它的那个 h文件中如何定义啊! 你自己又看不透彻,也不把相关的定义全部贴出来,就让我在这儿“猜”????
Private Declare Function EZLink_Connect Lib "EasyLink.dll" ( _
                           ByVal lpszServerName As String, _
                           ByVal wServerPort As Integer, _
                           ByVal lpszUser As String, _
                           ByVal lpszPassword As String, _
                           ByVal llTaskID_Low As Long, _
                           ByVal llTaskID_Hig As Long, _
                           ByVal proc As Long, _
                           ByVal dwProcParam As Long, _
                           ByVal lpszLocalIP As Long) As Long

Private Type LARGINT
  LowLong As Long
  HigLong As Long
End Type


' 调用示例:
Private Sub Command1_Click()
   Dim m_llTalkID As LARGINT
   Dim m_hLink    As Long

   ' 注意 INT64数据的赋值:
   ' 假设:  llTaskID = &H11223344AABBCCDD   ← 64bit整数
   m_llTalkID.LowLong = &HAABBCCDD
   m_llTalkID.HigLong = &H11223344
   m_hLink = EZLink_Connect("ServerName", 3965, "UserName", "PassWord", _
                        m_llTalkID.LowLong, m_llTalkID.HigLong, 0&, 0&, 0&)
End Sub
加载更多回复(14)

7,763

社区成员

发帖
与我相关
我的任务
社区描述
VB 基础类
社区管理员
  • VB基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧