最新某个需求,客户使用PB开发环境,而我们提供的是C++的DLL,因此,需要提供一个DLL,能够在PB环境下调用。折腾了一个工作日才解决问题,二进制的兼容性真是很多细节需要注意的。
首先,C++ DLL方面:
1 新建一个C++ DLL工程(Win32工程)。
2 编写dll导出函数,调用类型需要指定为_stdcall。比如 extern "C" _declspec(dllexport) int _stdcall fun1(char *name,char *password);
3 编写def模块文件,定义导出函数。如下只是简单的例子,具体的文法规则可查看def文件规范。
LIBRARY "TestDll" ;工程和编译生成的DLL名称都为TestDll
EXPORTS
fun1 @1 ;指定导出函数序号为1
def文件是为了防止C、C++的符号修饰造成其它语言调用C、C++ DLL时函数名称的可读性差的问题。def定义后,原有导出函数为什么,导出后会保存一致,PB调用接口的时候就非常方便而且清晰可见。
PowerBuilder方面:
1 声明调用函数。
Public Function Long fun1(ref String name, ref String password) library 'TestDll.dll'
函数原型和C++的保存一致。同时char *在PB中应该使用ref String传递指针方式。如果使用其它的参数类型PB和C、C++的需要保持一一对应。
2 调用该函数即可。
注意点:
1 传递参数,比如指针等,PB和C++中必须对应正确。如char * 在PB中需要使用Ref String,C++的int在PB中需要使用long类型。
2 传递结构体,PB和C++中的定义需要保持完全对应,同时结构体的大小需要保持一致,特别是传递结构体指针时,如果结构体大小不一致可能导致内存访问异常。特别是C、C++编译器会对结构体成员进行字节对齐优化处理,建议使用类似 #pragma pack (1) 定义指定C++结构体的对齐单位,防止PB和C++由于不一致的编译器导致的结构体内存布局不一致。