从其它平台迁移而来


之前用lazarus编写了使用IInterfacedll,可惜没有成功。当把IInterface编译到exe里时,功能正常,编译到dll里再在exe里调用就不正常,原因未深究,不过大致也知道是哪一类问题,至于还有没有其它问题,暂未可知。

闲来有空,有写了点Demo来,有了不少新发现,在此记录下:

  1. 只有使用exports导出的函数才能在dll外部调用

  2. 只有使用stdcall修饰的函数传参规则才与标准C的传参规则相同,其它遵守标准C传参规则的语言可以正常调用;否则,只有lazarus编写的程序可以正常调用

  3. 入参为string类型时,无论是否使用stdcall修饰,lazarus编写的程序调用正常,其它语言未测试

  4. 返回值或出参为string类型时,调用报External: ACCESS VIOLATION错误;但参数为PChar时,调用正常

  5. 入参/出参/返回值为结构体时,调用正常

  6. string类型传参是指针/引用拷贝,结构体传参是值拷贝

  7. string做入参时,由主调函数分配内存并增加引用计数被调函数执行时再次增加引用计数被调函数结束时减少引用计数,此时引用计数不为0不释放内存,主调函数结束时再次减少引用计数引用计数0释放内存,该内存由exe分配,因此释放不报错;做出参时,由被调函数执行时分配内存并增加引用计数被调函数返回时先赋值给主调函数的变量,增加引用计数,再结束被调函数减少引用计数主调函数结束时再次减少引用计数,此时引用计数0释放内存,但该内存是由dll分配,因此产生External: ACCESS VIOLATION错误

  8. string类型不适合在dllexe之间传参(尤其是出参)

  9. 返回值为对象时,调用异常;入参/出参为exe创建的对象时,调用正常

结论

根据测试得出的结论,可能不严谨:

  1. 指针做为形参入参/出参)传递没有问题,但必须遵守谁创建谁释放的原则;指针做为返回值可能会有隐患

  2. 对象传参实际传的是对象的指针,规则与指针相同

  3. 返回值适合传递值拷贝的类型,如整型浮点型布尔型结构体指针(但指针指向的内存要遵守谁创建谁释放的原则,不过一般不直接使用)等

  4. 字符串结构体的生命周期是由编译器维护的,使用需慎重