Delphi XE7调用C++动态库出现乱码问题回顾
事情源于有个客户需使用我们C++的中间件动态库来跟设备连接通讯,但是传入以及传出的字符串指针格式都不正确(出现乱码或是被截断),估计是字符编码的问题导致。以下是解决问题的过程:
我们C++中间件动态库的接口函数声明:
extern "C" bool __stdcall ExecuteTaskInFile(const char *szTaskID, const char *szInputFile, const char *szOutputFile, bool bSynch);
传入的字符串指针要求是Ansi编码。
我们给客户提供的Delphi例子是用Delphi7写的:
声明:
function ExecuteTaskInFile(szTaskID : Pchar; szInputFile:Pchar; szOutputFile:PChar; bSynch :boolean):boolean;stdcall;external 'XXXX.dll';
调用:
function ExecuteFileTask():boolean;
var
strTaskID:string;
begin
//略去若干注释
strTaskID := '';
Result := ExecuteTaskInFile(pchar(strTaskID), pchar('C:\Data\TestData\Input\Task.xml'), pchar('C:\Data\TestData\Output\TaskResult.xml'), true);
end;
但是该程序拿到客户处编译运行后出现一些莫名错误,据客户反馈,他们也是使用Delphi,因此怀疑方向一度转到传入的数据文件内容是否有错误上,但从客户处取回数据文件后测试也无问题。不得已,只能上门拜访了下客户,幸好不是很远。到了现场才得知用户使用的Delphi是Delphi XE7,已经是Borland将Delphi抛弃很多年以后的事情了,距离我使用过的Delphi7也已经是12年后了。
在客户现场查看动态库接口的日志,发现了如下的记录:
2018-10-15 13:28:14,318 [0x000012c0] INFO RUNNING 0 XXXX.XXXX Enter XXXX::ExecuteTaskInFile(TaskId:2)
而我们传入的TaskId其实是'20160222111817081',只取到了第一个字符,那么很有可能是传入的指针指向的字符串是使用Unicode编码的,其第二个字节是0x00被当作字符串结束符而截断了。
很多年没有关注Delphi,又回顾了下Delphi的历史,Delphi7还是Ansi编码的IDE,因此上面的代码调用C++动态库传入Ansi字符串没有问题, 而Delphi从2009开始完整正式支持Unicode,之后的XE7是2014年发布的。 Delphi在2009以后对应char*的类型为PWideChar,因此默认使用了Unicode编码,如果要用Ansi编码,必须是PAnsiChar。
这样看来,问题就简单明了了,将Delphi代码改成如下后测试通过:
声明:
function ExecuteTaskInFile(szTaskID : PAnsichar; szInputFile:PAnsichar; szOutputFile:PAnsiChar; bSynch :boolean):boolean;stdcall;external 'XXXX.dll';
调用:
function ExecuteFileTask():boolean;
var
strTaskID:string;
begin
strTaskID := '';
Result := ExecuteTaskInFile(pAnsichar(AnsiString(strTaskID)), pAnsichar('C:\Data\TestData\Input\Task.xml'), pAnsichar('C:\Data\TestData\Output\TaskResult.xml'), true);
end;
值得注意的是,当使用字符串变量传递时,必须加以AnsiString转换,而常量字符串参数则可不用,后面再仔细研究了。
总结:其实事情本不复杂,可以通过简单的沟通就了解到客户的使用场景以及动态库的调用日志然后做针对性的分析,但是我们常常会忽略一些细节从而做出一些片面的判断导致问题复杂化,遇到问题时按部就班,不放过一个细节,针对性的分析解决才是正确的做法。
忌 一叶蔽目,管中窥豹。
宜 审问慎思,明辨笃行。
Delphi XE7调用C++动态库出现乱码问题回顾的更多相关文章
- c#调用c++动态库的一些理解
调用c++动态库一般我们这样写 [DllImport("UCamer.dll", CallingConvention = CallingConvention.Winapi)] ...
- C#调用C++动态库(dll)
在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用re ...
- C#总结(四)调用C++动态库
由于公司很多底层的SDK,都是C++开发,上层的应用软件却是C# Winform程序.在实际工作的过程中,就经常碰到了C# 程序调用C++ 动态库的问题.最近一直在和C++ 打交道,C# 怎么调用C+ ...
- Java调用dll动态库
最近项目里使用java调用dll动态库,因此研究了一下这方面的东西. 使用的工具包如下 <dependency> <groupId>net.java.dev.jna</g ...
- 【C#】 使用Gsof.Native 动态调用 C动态库
[C#] 使用Gsof.Native 动态调用 C动态库 一.背景 使用C# 开发客户端时候,我们经常会调用一些标准的动态库或是C的类库.虽然C# 提供的PInvoke的方式,但因为使用的场景的多变, ...
- python调用.net动态库
# python调用.net动态库 ### pythonnet简介------------------------------ pythonnet是cpython的扩展- pythonnet提供了cp ...
- 使用ctypes在Python中调用C++动态库
使用ctypes在Python中调用C++动态库 入门操作 使用ctypes库可以直接调用C语言编写的动态库,而如果是调用C++编写的动态库,需要使用extern关键字对动态库的函数进行声明: #in ...
- C# 调用C++动态库注意事项
C# 调用C++动态库注意事项 最近项目上需要在C#中调用C++,期间遇到不少坑,总结如下: 1.in const char* 对应C#中string 或 IntPtr 2.out const ...
- JNI_Android项目中调用.so动态库
JNI_Android项目中调用.so动态库 2014年6月3日 JNI学习 參考:http://blog.sina.com.cn/s/blog_4298002e01013zk8.html 上一篇笔者 ...
随机推荐
- java 内存分析之堆栈空间
package Demo; public class Demo { public static void main(String[] args) { Demo demo = new Demo(); ; ...
- Pig autocomplete 自动补全
在pig的grunt环境下,按TAB键可以自动补全命令,用户可以添加自己的补全信息. 在conf目录下创建autocomplete文件,添加如下内容: hdfs://vm1:8020/ 在grun ...
- 3.CSS使用基础(2)
目录 一.CSS 链接 二.CSS 列表样式(ul) 三.CSS Table(表格) 四.盒子模型 五.CSS Border(边框) 六.CSS 轮廓(outline)属性 七.CSS Margin( ...
- centos7上安装 mysql
centos7上的安装是和其他的版本不一样的 ,因为centos上的安装与centos的操作是不通了的 在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装 ...
- 解决点击cell执行动画导致的重用问题
解决点击cell执行动画导致的重用问题 说明: 动画的细节都是裸露的,并没有封装,靠看官来优化了. 效果: 源码: https://github.com/YouXianMing/UITableView ...
- [翻译] UCZProgressView
UCZProgressView UCZProgressView is a circular progress indicator with cool animations for image load ...
- Redis学习---Redis操作之Set
Set操作,Set集合就是不允许重复的列表 sadd(name,values) name对应的集合中添加元素 --------------------------------------------- ...
- September 26th 2017 Week 39th Tuesday
I have to protect the one thing I can't live without. 我必须为我一生挚爱遮风挡雨. A man is a success if he gets u ...
- 移动端上下滑动事件之--坑爹的touch.js
下面的方法,不知道是操作方法不对还是啥. 在 zepto.js 里面加那一段代码不起作用 百度的 touch.js 是可以用的,但是使用方式 和 zepto有点不一样. 解决方案:参照这个链接地址 ...
- spring中MessageSource的配置使用方法2--ReloadableResourceBundleMessageSource【转】
本文转载仅供自己学习收录,不做任何商业用途,如有需要可访问原地址:http://blog.csdn.net/qyf_5445/article/details/8124362 如何在spring mvc ...