DLL库中的函数申明:ZLDS10X_Open(char * portnum , int baud , int timeout , int address)
在VB中Private Declare Function ZLDS10X_Open Lib "ZLDS10X" (ByVal Comx As String, ByVal baudrate As Long, ByVal timeout As Long, ByVal netaddress As Long) As Long
……
Private Sub Command1_Click()
……
ahandle = ZLDS10X_Open("com1", 115200, 1000, 1)
……调用一点问题都没有,做成EXE文件后运行也没问题,监测串口的工作也没有任何问题。但是问题是:
在VB环境下运行结束后,VB会弹出出错关闭对话框(就是那个可以发送错误报告的对话框),选择调试按钮后,在VC调试中提示好象是有invalid异常从VB中抛出,没有进行捕获。不知道是VB的问题还是什么说明一下:
这个DLL库是没问题的,在VC环境下作过各种测试,包括几百个小时的压力测试。
只不过调用了网上的开源的log4cpp,这个log4cpp是有内存泄露的,是否跟这个问题有关系?请高手帮帮忙,多谢!!

解决方案 »

  1.   

    函数原型没有返回值,VB 中应该声明为 Sub。
    既然有 Open 就应该有 Close,VC 通常不会自动释放/关闭资源。
      

  2.   

    不好意思,没有贴完整
    原型是:
    extern "C"  SENSOR_HANDLE __stdcall ZLDS10X_Open(char * portnum , int baud , int timeout , int address);宏SENSOR_HANDLE定义为的int我在后面加了ZLDS10X_Close也有相同问题然后我不管调用DLL库中的哪个函数都会发生关闭时候VB异常中断。
      

  3.   

    字符串指针访问越界。
    定义了extern "C"后,C字符串是以\0结束的,而VB的字符串为BSTR。更正办法如下:
    一、将ahandle = ZLDS10X_Open("com1", 115200, 1000, 1)改为ahandle = ZLDS10X_Open("com1" & chr(0), 115200, 1000, 1)
    二、如果上述步骤仍然失败,则如此进行:
    修改声明:
    Private Declare Function ZLDS10X_Open Lib "ZLDS10X" (Comx() As Byte, ByVal baudrate As Long, ByVal timeout As Long, ByVal netaddress As Long) As Long
    修改执行语句:
    Dim b() as byte
    b=StrConv("com1"+chr(0),vbFromUnicode)
    ahandle = ZLDS10X_Open(b(0), 115200, 1000, 1)
      

  4.   

    应该不是 \0 的问题,VB 在调用 API 函数时对字符串参数会自动进行处理的。extern "C" 自动变更了函数名,所以 VB 中的声明是不匹配的:
    http://topic.csdn.net/t/20040713/13/3170246.html
    http://www.cnblogs.com/hustcat/archive/2009/02/01/1382188.html
      

  5.   

    其实开始我也以为是函数导出名称的问题,但楼主是从DLL里看到的导出名称(说明导出函数名称正确),而且说能够调用(说明是STDCALL),只是运行结束后才出问题,应该是VB非法释放这个函数造成的野指针,所以考虑在参数进行变化。另外,由于没有函数原型,某些函数出于一些特殊原因,会在函数内部对实参进行内存释放,而VB会自动释放安全数组,从而引起内存访问错误,楼主可以在我上述第二种调用办法之后,再补上一句redim b(0)。如果不再出错,那么问题可能出在这儿。
      

  6.   

    1.确认dll中的函数是__stdcall(WINAPI)方式导出
    2.确认此dll收到参数后不是视参数地址为永久存在的(建议传入的字符串放在模块中作为全局字符使用)
      

  7.   

    3楼的金正日哥们
    先谢谢你的代码,但是你的代码不能执行成功啊错误在ahandle = ZLDS10X_Open(b(0), 115200, 1000, 1),意思好象是说b(0)的错误,我把b(0)改成b,可以执行通过,但是根本没有按期望打开串口啊.而且不光是这个函数的调用问题,库里的其他函数也一样,我还特地给DLL库增加了一个新的空函数,
    在VB中只调用这个空函数,结果也有同样的问题.现象:
    只要调用了DLL库中任何一个函数,都会在关闭程序后VB出现异常错误.
    而且程序执行过程中不会出现错误.是否根据这个现象可以判断是有野指针产生呢?
    还有没有其他原因导致这样的现象呢?目前我推断问题是出现在DLLMain函数中
      

  8.   

    TO西西:哈,到现在才发现啊。
    TO楼主:说明你的DLL代码有问题。
      

  9.   

    是笔误么:ZLDS10X_Open(char * portnum , int baud , int timeout , int address) 
    Private Declare Function ZLDS10X_Open Lib "ZLDS10X" (ByVal Comx As String, ByVal baudrate As Long, ByVal timeout As Long, ByVal netaddress As Long) As Long 
    别名的位置应该放DLL中的原函数名吧?你确定肯定及一定DLL里的名字是ZLDS10X_Open,而不是ZLDS10X么?
      

  10.   

    “我在后面加了ZLDS10X_Close也有相同问题 ”不好意思,我理解力不是很强。请问楼主,上面这句话是什么意思?
      

  11.   

    “你给DLL库增加的新的空函数”的声明是什么样的?贴出来看看?
      

  12.   

    其实我上面的说错了,extern "C"应该是让编译器使用C的函数命名方式,保持导出函数的名称,以便正确识别。另外,我在3楼的提法一点意义都没有,如果误导了楼主和观众,俺表最示深切的歉意。
    这里不是VB调用DLL库的问题,我看了一下DLL的源代码,估计是互斥量未释放,导致VB程序结束后计时器线程仍然处于运行状态,而VB本来就对多线程支持不太好,所以结束后出现错误提示。
      

  13.   

    谢谢各路高手的回答,我还在努力解决中回西西:““你给DLL库增加的新的空函数”的声明是什么样的?贴出来看看?”extern "C" void __stdcall ZLDS10X_abc(int abc);void __stdcall ZLDS10X_abc(int abc)
    {
    ;
    }
      

  14.   

    金正日哥们牛啊!的确是线程的问题。
    在DLL库中的DLLMAIN函数里启动了一个线程,DLL调用结束时没有将该线程关闭,所以VB报错。