关于调用dll的问题,平时VB接触的少,请帮助指导,谢谢!

蓝天-2022 2017-09-18 12:57:37
问题描述,我们正开发一个身份证ocx用于读取信息,厂商发给我一个dll,大部分都没有问题,只有在调用下面的函数时出现错误程序崩溃,我感觉是由于参数char* cFrontImgBuf,char* cRearImgBuf没有定义好导致的,请指导,该怎么定义 !
一、dll说明 :
SavePicToMemory
int SavePicToMemory(unsigned DeviceID, char* cFrontImgBuf,char* cRearImgBuf, int* iFrontLen, int* iRearLen)

功能介绍
读取当前图像数据块到内存。

形式参数
DeviceID:[输入] USB设备内部ID号,取值范围0-7。

cFrontImgBuf:[输出] 保存正面图像数据信息指针,不能为空。

cRearImgBuf:[输出] 保存反面图像数据信息指针,不能为空。

iFrontLen:[输出] 正面图像数据长度。

iRearLen:[输出] 反面图像数据长度。
二、VB中引用
'读取当前图像数据块到内存。
Public Declare Function SavePicToMemory Lib "C:\SS\Lib\ID81DLL.dll" (ByVal DeviceID As Long, ByRef cFrontImgBuf As String, ByRef cRearImgBuf As String, ByRef iFrontLen As Long, ByRef iRearLen As Long) As Integer

三、VB调用

Dim cFrontImgBuf As String
Dim cRearImgBuf As String
Dim iFrontLen As Long
Dim iRearLen As Long

lRetc = SavePicToMemory(6, cFrontImgBuf, cRearImgBuf, iFrontLen, iRearLen)
...全文
1298 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
蓝天-2022 2017-09-19
  • 打赏
  • 举报
回复
@chewinggum 脆皮大雪糕 谢谢! 项目组WEB程序员多,由于需要临时弄VB有点难度,总算解决了!感谢提供思路!
of123 2017-09-19
  • 打赏
  • 举报
回复
一般来说,对于其他平台开发的 DLL ,函数中的 char 指针参数,VB 中选用 String 型要用 Byval,选用Byte 型要用 ByRef。 最好不用 String,如果数据有非打印字符或任意数据的话。因为系统会将大于 127 的字节自动解释为东亚文字的首字节。当在字库中找不到匹配字符,会用 ? 替代。
蓝天-2022 2017-09-19
  • 打赏
  • 举报
回复
问题已解决,再次感谢大家,尤其感谢@chen8013 舉杯邀明月 指点迷津!
脆皮大雪糕 2017-09-19
  • 打赏
  • 举报
回复
从参数名称看来,我的理解是这个API的 2、3、4、5参数都是返回参数,其中2、3你要先传两个16M的byte数组进去作为接受数据的buffer。调用后,4,、5参数返回这两个数组的实际大小,然后你再从buffer中取走相应大小的数据。
舉杯邀明月 2017-09-18
  • 打赏
  • 举报
回复
其实这个API使用上的很多细节,楼主根本没说。 那就按通常情况,来“猜”一下吧。
Option Explicit

'  int SavePicToMemory(unsigned DeviceID, char* cFrontImgBuf,char* cRearImgBuf,
'                          int* iFrontLen, int* iRearLen)
' 如果这个 API函数需要在多个模块中使用、需要声明为 Public的,就需要把这个声明写到“标准模块”中
Private Declare Function SavePicToMemory Lib "C:\SS\Lib\ID81DLL.dll" ( _
                           ByVal DeviceID As Long, _
                           ByRef cFrontImgBuf As Any, _
                           ByRef cRearImgBuf As Any, _
                           ByRef iFrontLen As Long, _
                           ByRef iRearLen As Long) As Long


Private Sub Command1_Click()
' 应用示例:
   Dim arrBuffFront()   As Byte
   Dim arrBuffRear()    As Byte
   Dim lSizeFront As Long
   Dim lSizeRear  As Long
   Dim lRetValue  As Long

   ' 只知道“最大16M”,但不知道具体需要多大空间;
   '   那就按16M来申请啰,反正“两个16MB”也如今来说不算很大。
   lSizeFront = &H1000000
   lSizeRear = &H1000000
   ReDim arrBuffFront(lSizeFront - 1&)    ' 分配数据空间
   ReDim arrBuffRear(lSizeFront - 1&)     ' 下面这句调用中,设备ID按你实际情况传递
   lRetValue = SavePicToMemory(0&, arrBuffFront(0&), arrBuffRear(0&), lSizeFront, lSizeRear)
   ' 这个API的很多细节,你在帖子中并没有说清楚。
   ' 估计如果执行成功,lSizeFront 、lSizeRear中会返回实际的数据大小
   ' 文档中,应该有说明“函数返回值”为0表示成功、或1表示成功。
End Sub
hsg_hn 2017-09-18
  • 打赏
  • 举报
回复
我也遇到过C++ char* 数据类型,在VB6中没搞定,后来用vb.net 定义为IntPtr 才OK
蓝天-2022 2017-09-18
  • 打赏
  • 举报
回复
引用 3 楼 chewinggum 的回复:
Public Declare Function SavePicToMemory Lib "C:\SS\Lib\ID81DLL.dll" (ByVal DeviceID As Long, ByRef cFrontImgBuf As String, ByRef cRearImgBuf As String, ByRef iFrontLen As Long, ByRef iRearLen As Long) As Integer 这里参数类型要改一改,C的原型里,cFrontImgBuf和cRearImgBuf是char数组指针,对应VB传递byte数组,你需要把你的string用strconver之类的函数转换为字节数组再传递。 而且还要看一下C的源代码,因为这里面没有定义参数的大小,所以应该是以 /0作为字符串结束标志,所以你传递过去的数组屁股后面要加个0
请继续指导,从文档看cFrontImgBuf和cRearImgBuf是输出参数,从dll里获取扫描后的图像数据,最大输出位图数据大小为16M。 修改如下: 二、VB中引用 '读取当前图像数据块到内存。 Public Declare Function SavePicToMemory Lib "C:\SS\Lib\ID81DLL.dll" (ByVal DeviceID As Long, ByRef cFrontImgBuf As byte, ByRef cRearImgBuf As byte, ByRef iFrontLen As Long, ByRef iRearLen As Long) As Integer 三、VB调用 Dim cFrontImgBuf(0 to 10) As byte //输出参数 Dim cRearImgBu(0 to 10) As byte //输出参数 Dim iFrontLen As Long //输出参数 Dim iRearLen As Long //输出参数 lRetc = SavePicToMemory(6, cFrontImgBuf(0), cRearImgBuf(0), iFrontLen, iRearLen) 请指正!
赵4老师 2017-09-18
  • 打赏
  • 举报
回复
将字符串传递到 DLL 过程 通常,字符串应该使用 ByVal 方式传递到 APIs。Visual Basic 使用被称为 BSTR 的 String 数据类型,它是由自动化(以前被称为 OLE自动化)定义的数据类型。一个 BSTR 由头部和字符串组成,头部包含了字符串的长度信息,字符串中可以包含嵌入的 null 值。BSTR 是以指针的形式进行传递的,因而 DLL 过程能够修改字符串。(指针是一个变量,包含另外一个变量的内存地址,而不是数据。) BSTR 是 Unicode 的,即每个字符需要两个字节。BSTR 通常以两字节的 null 字符结束。 图 1.2 BSTR 类型(每一个框表示两个字节) DLL 中的大部分过程(以及 Window API 中的所有过程)能够识别 LPSTR 类型,这是指向标准的以 null 结束的 C 语言字符串的指针,它也被称为 ASCIIZ 字符串。LPSTR 没有前缀。下图显示了一个指向 ASCIIZ 字符串的 LPSTR。 图 1.3 LPSTR 类型 如果 DLL 过程需要一个 LPSTR(指向以 null 结束的字符串的指针)作为参数,可以将 BSTR 以使用值方式传递给它。因为指向 BSTR 的指针实际指向以 null 值结束的字符串的第一个数据字节,对于 DLL 过程来说,它就是一个 LPSTR。 例如,sndPlaySound 函数接受一个数字声音 (.wav) 文件名,然后演奏该文件。 Private Declare Function sndPlaySound Lib "winmm.dll" _ Alias "sndPlaySoundA" (ByVal lpszSoundName As String, _ ByVal uFlags As Long) As Long 因为该过程的字符串参数被声明为 ByVal,Visual Basic 将传递一个 BSTR,该 BSTR 指向第一个数据字节: Dim SoundFile As String, ReturnLength As Long SoundFile = Dir("c:\Windows\System\" & "*.wav") Result = sndPlaySound(SoundFile, 1) 通常,如果 DLL 过程需要 LPSTR 参数,那么使用 ByVal 关键字。如果 DLL 需要得到指向 LPSTR 的指针,则使用引用方式传递 Visual Basic 字符串。 如果要将二进制数据传递到 DLL 过程,可以将变量作为 Byte 数据类型的数组传递,不要将其作为 String 变量。字符串是假定用来包含字符的,如果将二进制数据作为 String 变量传递,外部程序可能无法正确读入数据。 假设声明了一个字符串变量,但没有初始化它,如果将其以使用值方式传递到 DLL,该字符串变量将作为 NULL 传递,而不是作为空字符串 ("")。为了消除代码中的混淆,如果要将 NULL 传递到 LPSTR 参数,请使用 vbNullString 常数。 将字符串传递到使用自动化的 DLL 某些 DLL 是专门使用 BSTR 等自动化数据类型的,它们利用了自动化提供的若干过程。 因为 Visual Basic 使用自动化数据类型作为自己的数据类型,所以能够使用引用方式将 Visual Basic 参数传递到需要自动化数据类型的任何 DLL。因此,如果 DLL 过程需要以 Visual Basic 字符串作为参数,就不必用 ByVal 关键字来声明参数,除非该过程确实需要以使用值方式传递字符串。 某些 DLL 过程可以返回字符串到调用它的过程。除非 DLL 函数是专门为自动化数据类型而编写的,否则它将不能返回字符串。如果确实能够返回字符串,该 DLL 可能会提供对过程进行描述的类型库。请参考该 DLL 的有关文档。 详细信息 关于自动化数据类型,请参阅 Microsoft Press 出版的 OLE 2 PROGRAMMER'S REFERENCE。 修改字符串参数的过程 DLL 过程能够修改作为参数输入的字符串变量的数据。不过,如果修改后的数据超过了原来的长度,过程的修改将越界(越过字符串的结尾),这可能会毁坏其它的数据。 要避免这个问题,一种办法是使字符串参数足够长,从而使 DLL 过程无法超出字符串的尾部。例如,GetWindowsDirectory 过程在第一个参数中返回了 Windows 目录的路径: Declare Function GetWindowsDirectory Lib "kernel32" _ Alias "GetWindowsDirectoryA" (ByVal lpBuffer As _ String, ByVal nSize As Long) As Long 在调用该过程时,为了安全起见,先使用 String 函数在字符串中填充 255 个空字符(二进制的 0),只要返回的路径少于 255 个字符,就不会出问题: Path = String(255, vbNullChar) ReturnLength = GetWindowsDirectory(Path, Len(Path)) Path = Left(Path, ReturnLength) 另一个办法是将字符串定义为定长的: Dim Path As String * 255 ReturnLength = GetWindowsDirectory(Path, Len(Path)) 上述方法的目的只有一个:创建一个固定长度的字符串,使之能够包含过程可能产生的最长的字符串。 注意 Windows API 的 DLL 过程通常不需要超过 255 个字符的字符串缓冲区。尽管这对于其它的许多库也是成立的,为了保险起见,最好参考相应过程的文档。 当 DLL 过程需要内存缓冲区时,既可以使用适合的数据类型,也可以使用字节数据类型的数组。
脆皮大雪糕 2017-09-18
  • 打赏
  • 举报
回复
Public Declare Function SavePicToMemory Lib "C:\SS\Lib\ID81DLL.dll" (ByVal DeviceID As Long, ByRef cFrontImgBuf As String, ByRef cRearImgBuf As String, ByRef iFrontLen As Long, ByRef iRearLen As Long) As Integer 这里参数类型要改一改,C的原型里,cFrontImgBuf和cRearImgBuf是char数组指针,对应VB传递byte数组,你需要把你的string用strconver之类的函数转换为字节数组再传递。 而且还要看一下C的源代码,因为这里面没有定义参数的大小,所以应该是以 /0作为字符串结束标志,所以你传递过去的数组屁股后面要加个0
赵4老师 2017-09-18
  • 打赏
  • 举报
回复
Dim cFrontImgBuf As String Dim cRearImgBuf As String 改为 Dim cFrontImgBuf As String*256 Dim cRearImgBuf As String*256 再试试看。
蓝天-2022 2017-09-18
  • 打赏
  • 举报
回复
VB论坛有没有人?

863

社区成员

发帖
与我相关
我的任务
社区描述
VB COM/DCOM/COM+
c++ 技术论坛(原bbs)
社区管理员
  • COM/DCOM/COM+社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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