http://bbs.csdn.net/topics/390870532

用delphi xe3写的DLL,delphi7调用,参数都是PAnsiChar,DLL里的函数接收delphi7传的入参,没有问题,为什么返回参数会是乱码???

Delphi XE3的DLL代码:

Delphi/Pascal code

 

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
library TestDll;
 
uses
  System.SysUtils,
  System.Classes;
 
  function Test(Instr1,Instr2:PAnsiCharvar retMsg:PAnsiChar):Integer;stdcall;
  var
    str1,str2:string;
  begin
    str1:=Instr1;  //此处Instr1、Instr2两个入参都正确,没有乱码,赋值给string变量也没问题
    str2:=Instr2;
    retMsg:=PAnsiChar(str1+'-'+str2);
    Result:=1;
  end;
 
exports
  Test;

Delphi7 调用代码

Delphi/Pascal code

 

?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type
  TTest=function(Instr1,Instr2:PChar; retMsg:PChar):Integer;stdcall;
……
……
var
  lhandle:THandle;
  ltest:TTest;
  retMsg:array[0..2000of AnsiChar;
begin
  lhandle:=LoadLibrary('TestDll.dll');
  if lhandle>32 then
  begin
    @ltest:=GetProcAddress(lhandle,'Test');
    if ltest(PChar(Edit1.Text),PChar(Edit2.Text),@retMsg)=1 then begin
      ShowMessage('调用成功,返回Msg:'+retMsg);  //此处retMsg是乱码,怎么回事?
    end;
  end;
end;

为什么返回参数会是乱码?定义的数据类型不对吗?
怎么定义含有字符串参数的动态库才可以让Delphi7、DelphiXE3还有其他语言通用?

 

回复次数:17

关注
u012072926
Liyp92
本版等级:

 
#1 得分:0回复于: 2014-08-26 09:09:42
我也写过一个这样的。
在XE2写到DLL在Delphi2010调用,一直出错。最后没办法只能装个2010编译我写到DLL,就可以了。
Delphi在处理版本之间的转换很不到位
关注
aniugee
aniugee
本版等级:

 
#2 得分:2回复于: 2014-08-26 09:15:21
function Test(Instr1,Instr2:PAnsiChar):PAnsiChar;stdcall;可以改成这样

str1,str2:string;
最好改成AnsiString

关注
ksrsoft
缘中人
本版等级:

 
  
#3 得分:2回复于: 2014-08-26 09:16:24
str1,str2:string;
换成
str1,str2:AnsiString试试

或者
retMsg:=PAnsiChar(   AnsiString( str1+'-'+str2)        );

关注
warrially
爱蹄子的羊头
本版等级:

 
#4 得分:2回复于: 2014-08-26 09:27:29
AnsiString 的问题.  string 不可以直接转成 PAnsiChar 的
关注
WW7CC7MM
WW7CC7MM
本版等级:

 
#5 得分:0回复于: 2014-08-26 10:17:28
用D7重新编译DLL嘛
关注
lxdddxl
lxdddxl
本版等级:

 
#6 得分:1回复于: 2014-08-26 12:18:19
接口函数两边的申明不一致,retMsg上面是变参,下面是形参
应该是D7的申明里漏了var
关注
wzgdyn
wzgdyn
本版等级:

 
#7 得分:0回复于: 2014-08-27 09:27:56
动态库修改
str1,str2:AnsiString;
或者
retMsg:=PAnsiChar(   AnsiString( str1+'-'+str2) );
可以,完全正确。

如果想要DelphiXE3写的DLL,用C++也可以调用,那么字符串的参数类型应该怎么定义? 
PAnsiChar类型可以吗?还是必须用Pchar ??

关注
wzgdyn
wzgdyn
本版等级:

 
#8 得分:0回复于: 2014-08-27 20:36:46
Delphi版的人越来越少了吗?????????
关注
hj3000
hj3000
本版等级:

 
#9 得分:20回复于: 2014-08-28 11:29:32
1 调用时type TTest=function(Instr1,Instr2:PChar; retMsg:PChar):Integer;stdcall;缺少Var标识。
2 D7的Pchar是PAnsiChar XE后是PWidechar。
不多说了
Library TestDll;

Uses
  System.SysUtils,
  System.Classes;

Function Test(Instr1, Instr2: PAnsiChar; Var retMsg: PAnsiChar): Integer; Stdcall;
Var
  str1, str2: String;
Begin
  str1 := String(Instr1);
  str2 := String(Instr2);
  //retMsg := PAnsiChar(ansiString(str1 + '-' + str2));
  StrCopy(retMsg, PAnsiChar(ansiString(str1 + '-' + str2)));
  Result := 1;
End;

Exports
  Test;

End.

Type
  TTest = Function(Instr1, Instr2: PAnsiChar; Var retMsg: PAnsiChar): Integer; Stdcall;
Var
  lhandle: THandle;
  ltest: TTest;
  retMsg: PAnsiChar;
Begin
  lhandle := LoadLibrary('TestDll.dll');
  If lhandle > 32 Then
  Begin
    @ltest := GetProcAddress(lhandle, 'Test');
    GetMem(retMsg, 256);
    If ltest(PChar(Edit1.Text), PChar(Edit2.Text), retMsg) = 1 Then
    Begin
      ShowMessage('调用成功,返回Msg:' + retMsg);
    End;
    FreeMem(retMsg);
  End;

Type
  TTest = Function(Instr1, Instr2: PAnsiChar; Var retMsg: PAnsiChar): Integer; Stdcall;
Var
  lhandle: THandle;
  ltest: TTest;
  retMsg: PAnsiChar;
Begin
  lhandle := LoadLibrary('TestDll.dll');
  If lhandle > 32 Then
  Begin
    @ltest := GetProcAddress(lhandle, 'Test');
    GetMem(retMsg, 256);
    If ltest(PAnsiChar(Ansistring(Edit1.Text)), PAnsiChar(Ansistring(Edit2.Text)), retMsg) = 1 Then
    Begin
      ShowMessage('调用成功,返回Msg:' + retMsg);
    End;
    FreeMem(retMsg);
  End;

关注
seleron
程晨c
本版等级:

 
#10 得分:0回复于: 2014-08-28 11:39:00
AnsiChar,在xe2和D7占1个字节
Char,在xe2中占2个字节,在D7占1个字节
关注
unearth
孤独de猫
本版等级:

 
#11 得分:0回复于: 2014-08-28 20:58:46
同意7楼的,,,DLL里面出来的数据有问题。
关注
yangb0803
道玄希言
本版等级:

 
 
#12 得分:0回复于: 2014-08-29 20:44:54
Delphi 好像是从 2010 开始,char,AnsiChar, widechar,  string, ansistring, widestring 占用的字节不一样了~

一定要注意,如果想高版本的程序移到低版本,就要注意字符定义必需一一对应了.

就如你dll时定义了PAnsiChar, 到了调用时,也需要 是PAnsiChar而不能用 pchar

关注
Tachibana_Kanade
铃仙
本版等级:

 
#13 得分:1回复于: 2014-08-30 22:12:16
引用 7 楼 wzgdyn 的回复:

动态库修改
str1,str2:AnsiString;
或者
retMsg:=PAnsiChar(   AnsiString( str1+'-'+str2) );
可以,完全正确。

如果想要DelphiXE3写的DLL,用C++也可以调用,那么字符串的参数类型应该怎么定义? 
PAnsiChar类型可以吗?还是必须用Pchar ??

随便,可以不用改,PAnsiChar就对应C++里的char*

关注
truexf
truexf
本版等级:

 
#14 得分:20回复于: 2014-08-30 23:39:48
lz的代码有这么几个问题:
1. 函数的签名不同,导出的是 var retMsg: PAnsiChar; 使用的却是 regMsg:Pansichar;后者无法接收到返回的值。
2. 导出函数使用UnicodeString(xe3string是UnicodeString),却硬生生的把他强制转换为PAnsiChar;
3. 函数返回的retMsg是由临时的函数内变量,函数结束,该变量消失。你获得的将是一个非法内存地址。
4. 对string的编译器自动引用计数管理认识不清,string的引用计数不能跨dll的,他是delphi特有的东西。

解决方法
1. 签名一致用 var PansiChar
2. 函数用GetMem分配内存,并使用Ansistring封装数据,然后复制到分配的内存中
3. 返回分配的内存地址

调用的函数负责释放内存。因此dll还需提供一个释放内存的导出函数(将Freemem封装成导出函数);

关注
wr960204
武稀松
本版等级:

 
#15 得分:2回复于: 2014-09-02 10:55:03
retMsg:=PAnsiChar(str1+'-'+str2);
str1+''+str2的内容是保存在临时变量中的,这个临时变量是局部变量,离开函数的时候就被回收了.
你转成PAnsiChar的地址指向的是无效的地址,之所以有时候会是正常的是因为内存管理器没有重用这块内存的话看上去像是对的.
关注
caonumber
caonumber
本版等级:

 
#16 得分:0回复于: 2014-09-13 21:30:25
string换成widestring试试看
关注
iamduo
iamduo
本版等级:

 
#17 得分:0回复于: 2014-09-18 13:24:42
PAnsiChar, PChar,string 都改成 WideString 试试看。

Delphi XE3写DLL,用Delphi7调用,报错!的更多相关文章

  1. [笔记]Delphi 2007写DLL供VC调用实例

    考虑如下几种常用情况: - VC传入int,返回int- VC传入char *,返回int- VC传入char *,返回char *及int 为简化问题,传递的字符串参数只考虑ANSI格式,不考虑UN ...

  2. Delphi 中的DLL 封装和调用对象技术(刘艺,有截图)

    Delphi 中的DLL 封装和调用对象技术本文刊登2003 年10 月份出版的Dr.Dobb's 软件研发第3 期刘 艺摘 要DLL 是一种应用最为广泛的动态链接技术但是由于在DLL 中封装和调用对 ...

  3. this.$Message.success('提示信息') 少写了一个c 导致报错

    this.$Message.success('提示信息') 少写了一个c 导致报错 而且 $Message 输出还没显示,导致我以为是没有 $Message 对象了,其实全局对象直接调用即可

  4. 解决alaert.builder二次调用报错的bug

    报错的代码是: The specified child already has a parent. You must call removeView() on the child's parent f ...

  5. 记录一次在Github写博客时的报错和解决方法

    前几天刚刚搭建好了Github博客,打算用作记录Go语言学习笔记.由于在此前我没有使用过markdown语法写过博客,所以跟着文档了解了格式就想试试, 发表第一篇博客.markdown编辑器我用的是T ...

  6. 【Linux开发】OpenCV在ARM-linux上的移植过程遇到的问题1---cvNamedWindow调用报错的问题

    问题描述: 这个实际上是最后一部的问题,将生成的共享库文件放入到了/usr/local/opencv-arm/lib下,并且设置了LD_LIBRARY_PATH中为/usr/local/opencv- ...

  7. .Net Core redis 调用报错 '6000 Redis requests per hour' 解决 6000 此调用限制

    问题描述 redis 是一种基于内存,性能高效的 NoSQL 数据库,性能高主要就体现在数据交互耗时较短,能够段时快速的对用户的请求做出反应,所以在业务比较复杂或交互量需求大时,必然会超过 6000次 ...

  8. Django 调用报错 " ImportError: Couldn't import Django. "

    系统炸了导致不得已重装 安装 Django后 利用ORM 创建表的时候报错 Traceback (most recent call last): File "manage.py", ...

  9. python已写内容中可能的报错及解决办法

    理论上我发的每个短文,直接复制放到py里面,python xx.py是可以执行的,不过因为版本,编码什么的问题会有报错,详见这里 报错: SyntaxError: Non-ASCII characte ...

随机推荐

  1. Java中关键字static的使用

    static 关键字 1).static只能修饰成员变量或成员方法,所有非静态是对象相关的,所有静态是类相关的. 2)被static修饰的成员变量成员方法独立于该类的任何对象,它不依赖类的特定的实例, ...

  2. MVC中利用knockout.js实现动态uniqueId

    题目比较拗口,但是这篇文章确实直说这一点. knockout.js是一个JS库,它的官网是http://knockoutjs.com/ 这篇文章的重点是knockout在工作的一个功能中的应用.最终效 ...

  3. System.Runtime.InteropServices.COMException: 检索 COM 类工厂中 CLSID 为 {0002E510-0000-0000-C000-000000000046} 的组件时失败,原因是出现以下错误: 80040154

    这个问题困恼我好几天了,今天终于解决. 开始我在网上左百度右google,都没搜到最终的解决方案,今天我把解决方案贴出来,以供大家分享! 网上有些是报80070005错误的,跟我这个80040154错 ...

  4. c++智能指针(1)

    根据muduo开源库作者陈硕的一些文章.对于多线程下C++编程提出了一些观点.主要是多线程下对象的销毁比较困难,但是由于多线程下,mutext是无法保护析构的.而后提出了智能指针的方案并对使用该指针会 ...

  5. 通过SD卡来安装Linux系统

    一.制作SD启动卡(安装Linux)步骤: 烧写原理:superboot-6410.bin(bootloader)+内核镜像文件+根文件系统 1.将SD卡插入USB接口的读卡器,并插在PC的USB口 ...

  6. vb中去掉string数组的一部分

    今天碰到一个问题,登陆的时候,如果不需要验证手机号为空,则不去验证手机号 因为登陆的时候所有的验证信息都存放在一个数组里 Dim CheckUserInfo() As String ={UserBir ...

  7. Bootstrap的起步

    -- Bootstrap的起步部分是对Bootstrap的基本了解,有些细节只是在后面的完善时候需要详细阅读. 最基本点还是Css 和组件部分,这部分应该先进行练习....高级阶段是Javascrip ...

  8. 销售vs技术岗,做技术的方法思考

    销售甚至比技术岗位挣得还多,当然,做技术的比较好的拿到的自然也多. 我在想个问题,技术的天然优势是可以不断地积累,包括写code,写博客,做流程,完善流程,自动化流程,或者把某些工作流程化,自动化,托 ...

  9. 【搜索】 Prime Path

    #include<cstdio> #include<cstring> #include<cmath> #include<queue> #include& ...

  10. Flex 确定弹出窗口的绝对位置x , y

    var selectbox:Selectbox; selectbox = new SelectBox(); var pt:Point = new Point(0,0); pt = this.paren ...