为什么我在VC里写的DLL函数不带形参就能被VB调用,
带了一个int形参,VB调用时就会出现“DLL调用约定错误“呢?

解决方案 »

  1.   

    http://www.china-pub.com/computers/eMook/0624/info.htm
      

  2.   

    调用函数的声明:void (*fuc)(int)
      

  3.   

    声明函数时必须要加上WINAPI宏。
    背景:
        调用函数的时候,有各种不同的调用约定。它们规定了参数的传送方式、参数是否可变,由谁来处理堆栈等。常用的调用约定有两种:C语言调用约定和Pascal语言调用约定。
    1、C语言调用约定
       采用C语言编程的时候,默认使用C语言调用约定。也可以手工指定,这需要在函数声明时加上__cdecl关键字。采用本约定时,参数从右到左入栈,个数可变。由于返回的代码是固定了的,函数体不能预先知道传进来的参数个数,因此采用本约定时必须由调用函数者负责堆栈清理。由于参数可变,此约定比较灵活,但是性能比较低。
    2、Pascal语言调用约定
       大部分的Windows API都采用Pascal语言调用约定。采用C语言编程的时候,如果要采用这种调用约定,需要在函数声明的时候加上__stdcall关键字。windows.h头文件中也定义了一个WINAPI的宏,起同样的作用。采用本约定时,参数从右到左入栈,个数固定。因此,函数体本身就能知道传进来的参数个数,可以用一条ret n指令直接清理堆栈。牺牲灵活性换来的,是性能的提高。
    除了这两种调用约定,VC++中还有其他的调用约定,其中最重要的是This调用约定。
    3、This调用约定
       用于C++中的非静态类成员函数,它只能被编译器使用,没有相应的关键字。在Intel IA32架构下,此调用约定跟C语言调用约定相同,只是另外通过ECX寄存器传送一个额外的参数—this指针。
    4、快速调用约定
       这种调用约定用于对性能要求非常高的场合,关键字是__fastcall。在Intel IA32架构下,此调用约定将函数最左边两个大小小于4个字节(DWORD的大小)的参数放在ECX和EDX寄存器,其余规定同Pascal调用约定。
    5、裸调用约定
       当嵌入式汇编程序员需要手工控制调用约定的时候,使用这种方法。它没有相应的关键字,但是有一个__declspec(naked)用来指定这种调用约定。它不能用于函数声明,只能用于函数定义,也就是说,它只能让编译器不要生成函数体中的堆栈管理代码,但是调用函数者依然需要前面的某种调用约定来生成调用函数的代码。
      

  4.   

    重要更正:
    This调用约定类似于Pascal语言调用约定而不是C语言调用约定。