Delphi XE3写DLL,用Delphi7调用,报错!

wzgdyn 2014-08-25 10:07:52
用delphi xe3写的DLL,delphi7调用,参数都是PAnsiChar,DLL里的函数接收delphi7传的入参,没有问题,为什么返回参数会是乱码???

Delphi XE3的DLL代码:

library TestDll;

uses
System.SysUtils,
System.Classes;

function Test(Instr1,Instr2:PAnsiChar; var 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 调用代码

type
TTest=function(Instr1,Instr2:PChar; retMsg:PChar):Integer;stdcall;
……
……
var
lhandle:THandle;
ltest:TTest;
retMsg:array[0..2000] of 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还有其他语言通用?


...全文
832 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
iamduo 2014-09-18
  • 打赏
  • 举报
回复
PAnsiChar, PChar,string 都改成 WideString 试试看。
caonumber 2014-09-13
  • 打赏
  • 举报
回复
string换成widestring试试看
武稀松 2014-09-02
  • 打赏
  • 举报
回复
retMsg:=PAnsiChar(str1+'-'+str2); str1+''+str2的内容是保存在临时变量中的,这个临时变量是局部变量,离开函数的时候就被回收了. 你转成PAnsiChar的地址指向的是无效的地址,之所以有时候会是正常的是因为内存管理器没有重用这块内存的话看上去像是对的.
「已注销」 2014-08-30
  • 打赏
  • 举报
回复
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封装成导出函数);
铃仙 2014-08-30
  • 打赏
  • 举报
回复
引用 7 楼 wzgdyn 的回复:
动态库修改 str1,str2:AnsiString; 或者 retMsg:=PAnsiChar( AnsiString( str1+'-'+str2) ); 可以,完全正确。 如果想要DelphiXE3写的DLL,用C++也可以调用,那么字符串的参数类型应该怎么定义? PAnsiChar类型可以吗?还是必须用Pchar ??
随便,可以不用改,PAnsiChar就对应C++里的char*
道玄希言 2014-08-29
  • 打赏
  • 举报
回复
Delphi 好像是从 2010 开始,char,AnsiChar, widechar, string, ansistring, widestring 占用的字节不一样了~ 一定要注意,如果想高版本的程序移到低版本,就要注意字符定义必需一一对应了. 就如你dll时定义了PAnsiChar, 到了调用时,也需要 是PAnsiChar而不能用 pchar
程晨c 2014-08-28
  • 打赏
  • 举报
回复
AnsiChar,在xe2和D7占1个字节 Char,在xe2中占2个字节,在D7占1个字节
hj8090 2014-08-28
  • 打赏
  • 举报
回复
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;
孤独de猫 2014-08-28
  • 打赏
  • 举报
回复
同意7楼的,,,DLL里面出来的数据有问题。
wzgdyn 2014-08-27
  • 打赏
  • 举报
回复
动态库修改 str1,str2:AnsiString; 或者 retMsg:=PAnsiChar( AnsiString( str1+'-'+str2) ); 可以,完全正确。 如果想要DelphiXE3写的DLL,用C++也可以调用,那么字符串的参数类型应该怎么定义? PAnsiChar类型可以吗?还是必须用Pchar ??
wzgdyn 2014-08-27
  • 打赏
  • 举报
回复
Delphi版的人越来越少了吗?????????
lxdddxl 2014-08-26
  • 打赏
  • 举报
回复
接口函数两边的申明不一致,retMsg上面是变参,下面是形参 应该是D7的申明里漏了var
WW7CC7MM 2014-08-26
  • 打赏
  • 举报
回复
用D7重新编译DLL嘛
爱蹄子的羊头 2014-08-26
  • 打赏
  • 举报
回复
AnsiString 的问题. string 不可以直接转成 PAnsiChar 的
缘中人 2014-08-26
  • 打赏
  • 举报
回复
str1,str2:string; 换成 str1,str2:AnsiString试试 或者 retMsg:=PAnsiChar( AnsiString( str1+'-'+str2) );
aniugee 2014-08-26
  • 打赏
  • 举报
回复
function Test(Instr1,Instr2:PAnsiChar):PAnsiChar;stdcall;可以改成这样 str1,str2:string; 最好改成AnsiString
Liyp92 2014-08-26
  • 打赏
  • 举报
回复
我也写过一个这样的。 在XE2写到DLL在Delphi2010调用,一直出错。最后没办法只能装个2010编译我写到DLL,就可以了。 Delphi在处理版本之间的转换很不到位

16,748

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 语言基础/算法/系统设计
社区管理员
  • 语言基础/算法/系统设计社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧