VB调用VC++的DLL问题:原因可能是托管的PInvoke 签名与非托管的目标签名不匹配。请检查PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。

来源:互联网 发布:天翼网络对讲机 编辑:程序博客网 时间:2024/05/16 12:01

                前几天在.net framework4下实现了VB调用VC++Dll的一些工作,然而,每当VC的被调用函数返回时总是报错,如题。。

               原函数声明如下:extern ”C“__declspec(dllexport) void tt(int  num);VB中调用如下:Public Declare Sub tt  Lib "**.dll" (ByVal intnum As Integer)

               google之……找到了一些解决方案:

               1.有人说是参数类型传递错误,提出了一些在VB中将integer修改为int16、int32,将VC++中的int*在VB中使用IntPtr等方案。结果无用。

               2.看到有人建议好好读一读这个错误。在相关解决方案中了解了_cdecl 和_stdcall是神码??(毕竟不是计算机出身啊,这些可能是基础知识吧)。http://www.cnitblog.com/sonery/archive/2008/02/19/39925.html有比较详细的介绍。读了一下错误认为是VB调用后参数堆栈的释放方式比较不一致,即该函数调用约定

(calling convention)没设定好。于是我按照一些人建议的修改如下extern ”C“__declspec(dllexport) void _stdcall tt(int  num);VB中声明方式不变,还是不行(错误是“在该Dll中找不到tt的入口点”,仿佛又回到上一节中的情况中去了,其实是正常的_stdcall 会改变编译后函数的名字加上一些命名规则,很麻烦)。extern ”C“__declspec(dllexport) void  _cdecl  tt(int  num);VB中声明方式不变,也是不行(_cdecl  是complier默认的方式)。。

               3.后来发现http://www.tsking.net/archiver/?tid-10852.html用了这种VB中声明引用函数的方式。。

<DllImport("zlib.dll", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl)> Public Shared Function uncompress(ByVal dest As Byte(), ByRef destLen As Integer, ByVal src As Byte(), ByVal srcLen As Integer) As Integer
    End Function

其实很常见,但是本人从未研究过呵呵。。经验不足。今天想还是仔细研究一下。。文章说使用CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cdecl

解决了他的上述问题。。那我想还是试试吧。

            VB中声明如下:

<DllImport("zlib.dll", CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> Public Shared Sub tt(ByVal num As integer) 
 End Sub(注意我定义的是Sub,因为VC++中tt没有返回值的)

           居然好了!

          我很奇怪,刚才还报错找不到入口点,怎么一下子连调用约定也正常了??

回头一看,哦,原来我VC++中函数声明刚刚改为extern ”C“__declspec(dllexport) void  _cdecl  tt(int  num);了也就是说VB中设定的调用方式和VC++中声明的方式一致了。那么不管是由调用者还是被调用者来销毁参数堆栈,那都是ok的。。

             为了验证这个想法,我在VC++中修改为extern ”C“__declspec(dllexport) void  _cdecl  tt(int  num);VB中声明处改为

<DllImport("zlib.dll", CallingConvention:=System.Runtime.InteropServices.CallingConvention.Cedcl)> Public Shared Sub tt(ByVal num As integer) 
  End Sub

            也是ok的。。



原创粉丝点击