从其它平台迁移而来
之前用lazarus编写了使用IInterface的dll,可惜没有成功。当把IInterface编译到exe里时,功能正常,编译到dll里再在exe里调用就不正常,原因未深究,不过大致也知道是哪一类问题,至于还有没有其它问题,暂未可知。
闲来有空,有写了点Demo来,有了不少新发现,在此记录下:
-
只有使用
exports导出的函数才能在dll外部调用 -
只有使用
stdcall修饰的函数传参规则才与标准C的传参规则相同,其它遵守标准C传参规则的语言可以正常调用;否则,只有lazarus编写的程序可以正常调用 -
入参为
string类型时,无论是否使用stdcall修饰,lazarus编写的程序调用正常,其它语言未测试 -
返回值或出参为
string类型时,调用报External: ACCESS VIOLATION错误;但参数为PChar时,调用正常 -
入参/出参/返回值为
结构体时,调用正常 -
string类型传参是指针/引用拷贝,结构体传参是值拷贝 -
string做入参时,由主调函数分配内存并增加引用计数,被调函数执行时再次增加引用计数,被调函数结束时减少引用计数,此时引用计数不为0不释放内存,主调函数结束时再次减少引用计数,引用计数为0释放内存,该内存由exe分配,因此释放不报错;做出参时,由被调函数执行时分配内存并增加引用计数,被调函数返回时先赋值给主调函数的变量,增加引用计数,再结束被调函数,减少引用计数,主调函数结束时再次减少引用计数,此时引用计数为0释放内存,但该内存是由dll分配,因此产生External: ACCESS VIOLATION错误 -
string类型不适合在dll和exe之间传参(尤其是出参) -
返回值为
对象时,调用异常;入参/出参为exe创建的对象时,调用正常
结论
根据测试得出的结论,可能不严谨:
-
指针做为形参(入参/出参)传递没有问题,但必须遵守谁创建谁释放的原则;指针做为返回值可能会有隐患 -
对象传参实际传的是对象的指针,规则与指针相同 -
返回值适合传递值拷贝的类型,如整型、浮点型、布尔型、结构体、指针(但指针指向的内存要遵守谁创建谁释放的原则,不过一般不直接使用)等 -
字符串、结构体的生命周期是由编译器维护的,使用需慎重