在一个模块里声明了dll函数,并写了funtion,在其中调用了dll函数,并在主程序中调用了funtion,调试时调用dll函数时抱错“dll调用约定错误”,编译后,运行程序无此错误,但抱程序错误“内存不能读也不能写”?可以认定dll函数调用成功了,这是怎么回事啊?该怎么解决?

解决方案 »

  1.   

    用c写的dll,调用约定要改成__stdcall,而不是却省的_cdecl*方式。
      

  2.   

    但如果我编译执行程序,则不会出现“dll调用约定错误”,而且dll函数调用成功啊,但是vb会提示“未设置对象变量”??肯定是一调用了dll函数,便会这样的,程序代码本身没问题啊!能告诉我怎么回事啊?被这个查不出来的错误快逼疯了!!下面是dll的.h文件里的开头内容:
    #ifdef __cplusplus
    extern "C" {
    #endif
    这个就是那个调用声明吗?我不太懂,这是vb能调用的模式吗?如果不行,要怎么办?dll我是改不了的,是第三方的dll,我要在vb里用里面的函数!
      

  3.   

    //dll我是改不了的,是第三方的dll,我要在vb里用里面的函数!如果这个DLL的函数不是 _stdcall ,那么最好不要用,即使勉强能用,但实际上会破坏系统堆栈的平衡http://community.csdn.net/Expert/topic/3654/3654315.xml?temp=.1760675
      

  4.   

    方法1 : 调用那个函数完毕后,自己修复堆栈。其实C调用和stdcall调用的差别就在于,c调用是调用者恢复堆栈,而stdcall是被调用者恢复堆栈。而VB在调用所有的dll函数的时候都是采用stdcall的方式。见下面的示意代码:StdCall :   push arg2
       push arg1
       call func这就是stdcall方式调用 func( arg1,arg2 )的代码CCall:   push  arg2
       push  arg1
       call  func
       add   esp,8多出来的一句就是恢复堆栈的代码,注意,只要让esp + 4 * 参数个数,堆栈就可以恢复。这样就需要在VB里面插入机器码来直接操作esp寄存器,具体如何插入汇编代码可以参看网上的文章。因为只是插入一句代码,所以也可以静态修改编译出的文件来实现。方法2: 自己用VC重新包装那个dll,也就是在VC里面定义一个新的函数:__stdcall func( arg1, arg2 )
    {
         oldfunc( arg1,arg2 );
    }这里要注意,oldfunc要声明为 cdecl约定的,然后把这个源文件编译成一个obj文件,连接到VB工程中。当然,重新封装一个dll也是可以的,但是那样发布的时候就需要发布两个dll了,有点太麻烦。
      

  5.   

    没办法了,我暂时在调用过dll后 On Error Resume Next了一下,问题解决。谢谢各位了。