事情源于有个客户需使用我们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++动态库出现乱码问题回顾的更多相关文章

  1. c#调用c++动态库的一些理解

    调用c++动态库一般我们这样写   [DllImport("UCamer.dll", CallingConvention = CallingConvention.Winapi)] ...

  2. C#调用C++动态库(dll)

    在实际软件开发过程中,由于公司使用了多种语言开发,在C#中可能需要实现某个功能,而该功能可能用其他语言已经实现了,那么我们可以调用其他语言写好的模块吗?还有就是,由于C#开发好的项目,我们可以利用re ...

  3. C#总结(四)调用C++动态库

    由于公司很多底层的SDK,都是C++开发,上层的应用软件却是C# Winform程序.在实际工作的过程中,就经常碰到了C# 程序调用C++ 动态库的问题.最近一直在和C++ 打交道,C# 怎么调用C+ ...

  4. Java调用dll动态库

    最近项目里使用java调用dll动态库,因此研究了一下这方面的东西. 使用的工具包如下 <dependency> <groupId>net.java.dev.jna</g ...

  5. 【C#】 使用Gsof.Native 动态调用 C动态库

    [C#] 使用Gsof.Native 动态调用 C动态库 一.背景 使用C# 开发客户端时候,我们经常会调用一些标准的动态库或是C的类库.虽然C# 提供的PInvoke的方式,但因为使用的场景的多变, ...

  6. python调用.net动态库

    # python调用.net动态库 ### pythonnet简介------------------------------ pythonnet是cpython的扩展- pythonnet提供了cp ...

  7. 使用ctypes在Python中调用C++动态库

    使用ctypes在Python中调用C++动态库 入门操作 使用ctypes库可以直接调用C语言编写的动态库,而如果是调用C++编写的动态库,需要使用extern关键字对动态库的函数进行声明: #in ...

  8. C# 调用C++动态库注意事项

    C# 调用C++动态库注意事项 最近项目上需要在C#中调用C++,期间遇到不少坑,总结如下: 1.in const char*   对应C#中string 或  IntPtr 2.out const ...

  9. JNI_Android项目中调用.so动态库

    JNI_Android项目中调用.so动态库 2014年6月3日 JNI学习 參考:http://blog.sina.com.cn/s/blog_4298002e01013zk8.html 上一篇笔者 ...

随机推荐

  1. java基础(八) 深入解析常量池与装拆箱机制

    引言   本文将介绍常量池 与 装箱拆箱机制,之所以将两者合在一起介绍,是因为网上不少文章在谈到常量池时,将包装类的缓存机制,java常量池,不加区别地混在一起讨论,更有甚者完全将这两者视为一个整体, ...

  2. Week4——Hello.java分析

    如下图源码所示: 该段代码声明了一个entity实体类,该类有一个变量name,对该变量写了对应的get和set方法.类中还有一个空的构造方法hello(). @RequestScoped用于指定一个 ...

  3. 转载:http://www.cnblogs.com/double-K/p/6926367.html

    sql专家感悟:不可说的感悟-——十年老技术转型(一) http://www.cnblogs.com/double-K/p/6926367.html

  4. 6.JXL操作Excel

    一.简介 jxl是一个韩国人写的java操作excel的工具, 在开源世界中,有两套比较有影响的API可 供使用,一个是POI,一个是jExcelAPI.其中功能相对POI比较弱一点.但jExcelA ...

  5. [翻译] USING GIT IN XCODE [4] 在XCODE中使用GIT[4]

    USING GIT IN XCODE LOOKING AT HISTORY Xcode provides a Versions editor, which has three different pe ...

  6. Python学习---IO的异步[asyncio +aiohttp模块]

    aiohttp aiohttp是在asyncio模块基础上封装的一个支持HTTP请求的模块,内容比8.4.2[基于asyncio实现利用TCP模拟HTTP请求]更全面 安装aiohttp: pip3 ...

  7. Nginx-基础配置

    正文 本文转载自:http://www.ha97.com/5194.html 文章经过我排版和润色再加工,更加易读.实在是了解nignx配置的基础好文章. 正文 定义Nginx运行的用户和用户组 us ...

  8. word用宏命令完美解决列表编号变黑块的问题

    相信很多人跟我一样,多次定义新的多级列表,会导致列表编号变成下面这样黑块 在百度搜索结果尝试了鼠标左键选中应用样式,文档关闭后打开问题依旧: 还是得感谢万能的Google,帮我找到了答案. 问题根因: ...

  9. ZT eoe android4.2 Bluetooth记录01-结构和代码分布

    android4.2 Bluetooth记录01-结构和代码分布 作者:cnhua5更新于 08月21日访问(697)评论(2) 在android4.2中,Google更换了android的蓝牙协议栈 ...

  10. 【4】python函数基础

    ---恢复内容开始--- 案例1:时间下一秒程序 #__author:"吉勇佳" #date: 2018/10/14 0014 #function: timestr=input(& ...