Qt与vs编写的dll通讯遇中的坑
Qt与vs编写的dll通讯遇中的坑
一、前言:
因为实际开发过程中遇到Qt调用vs编写的sdk,故用vs封装成纯C++的dll提供Qt使用,因为懒得迁移整个工程到Qt环境,毕竟没学过Qt,光是搭建环境,怎么使用creator就很多时间折腾了,时间成本很高。
二、新建vs的dll
1、生成dll、lib
2、新建Qt工程,把包含头文件
3、配置lib
4、dll放到exe目录下
5、编写客户端daim
int main(int argc, char *argv[])
{
TreeBuilder builder;
builder.test01();
std::string tt=builder.getString(temp);
qDebug()<<tt.c_str()<<endl;
}
6、运行看效果
三、原因分析和解决方法
1、原因是,字符集编码不一样,导致同一块内存两种含义,详细请看上一节讲解:https://blog.****.net/LittleLittleFish_xyg/article/details/83896107
2、如何解决呢?
既然c++的string有这个陷阱,解决方法为换一种传入的参数,改为unsigned char *,内部再使用unsigned char *到string的转换(注意用char,跨平台还可能是陷阱)
请仔细查看修改后的实现
3、客户端代码
int main(int argc, char *argv[])
{
unsigned char str_temp[]="world";
TreeBuilder builder;
builder.test01();
unsigned char* tt=builder.getString(str_temp);
char *buf = reinterpret_cast<char*>(tt);
qDebug()<<"return:"<<buf<<endl;
}
4、运行结果:
四、new对象产生的坑(遗留的bug,还没有找到解决方法)
描述:dll中使用了new操作符,并在dll中使用该指针,vs工厂调用dll能正常使用dll中的指针,但是Qt调用vs的dll不正常,于是将vs的dll和Qt进程联调进入dll的运行代码中发现,new出来并赋值后的内存全部为空,导致不可收拾的灾难。
个人理解:dll中的new实际上是exe的进程地址空间(这方面的知识可以在window核心编程的资料中看到),即vs工程exe调用dll时,dll中new出来的地址,是vs工程的进程地址,而Qt调用dll时是qt进程的地址,由于两种进程地址存在差异导致内存不能正常读取,Qt编码UTF-8,vs的是Unicode。当vs编译dll时候,认为你用Unicode的方式找到这个内存,而qt调用的dll的时候,却根据utf-8的内存来读写,dll中new出来的地址A,在qt进程确是对应B的地址位置,这时候还查看A地址,当然是有问题的(对逻辑地址的理解还不够,不知道是否正确,仅供参考)
如有大神指导一下这个bug的解决方法,实在感激不尽!因为这个bug的缘故,导致我放弃VS写这个sdk,改用Qt。
五、总结
跨平台一定要谨慎,能不夸尽量不跨,当然高手另当别说,对于新手各种细节不理解,出现各种问题不知如何寻求答案,经常一个小问题导致好几天没有进度。本来是想解救一下bug,却发现还留了一个坑,最后还是走了迁移代码的路!
下一节介绍Qt工程如何联调vs的dll工程