标签:
http://bbs.csdn.net/topics/390870532
用delphi xe3写的DLL,delphi7调用,参数都是PAnsiChar,DLL里的函数接收delphi7传的入参,没有问题,为什么返回参数会是乱码???
Delphi XE3的DLL代码:
Delphi7 调用代码
为什么返回参数会是乱码?定义的数据类型不对吗? 怎么定义含有字符串参数的动态库才可以让Delphi7、DelphiXE3还有其他语言通用? |
||||
|
#1 得分:0回复于: 2014-08-26 09:09:42
我也写过一个这样的。
在XE2写到DLL在Delphi2010调用,一直出错。最后没办法只能装个2010编译我写到DLL,就可以了。 Delphi在处理版本之间的转换很不到位 |
#2 得分:2回复于: 2014-08-26 09:15:21
function Test(Instr1,Instr2:PAnsiChar):PAnsiChar;stdcall;可以改成这样
str1,str2:string; 最好改成AnsiString |
|
#3 得分:2回复于: 2014-08-26 09:16:24
str1,str2:string;
换成 str1,str2:AnsiString试试 或者 retMsg:=PAnsiChar( AnsiString( str1+‘-‘+str2) ); |
|
#4 得分:2回复于: 2014-08-26 09:27:29
AnsiString 的问题. string 不可以直接转成 PAnsiChar 的
|
|
#5 得分:0回复于: 2014-08-26 10:17:28
用D7重新编译DLL嘛
|
|
#6 得分:1回复于: 2014-08-26 12:18:19
接口函数两边的申明不一致,retMsg上面是变参,下面是形参
应该是D7的申明里漏了var |
|
#7 得分:0回复于: 2014-08-27 09:27:56
动态库修改
str1,str2:AnsiString; 或者 retMsg:=PAnsiChar( AnsiString( str1+‘-‘+str2) ); 可以,完全正确。 如果想要DelphiXE3写的DLL,用C++也可以调用,那么字符串的参数类型应该怎么定义? PAnsiChar类型可以吗?还是必须用Pchar ?? |
|
#8 得分:0回复于: 2014-08-27 20:36:46
Delphi版的人越来越少了吗?????????
|
|
#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; |
|
#10 得分:0回复于: 2014-08-28 11:39:00
AnsiChar,在xe2和D7占1个字节
Char,在xe2中占2个字节,在D7占1个字节 |
|
#11 得分:0回复于: 2014-08-28 20:58:46
同意7楼的,,,DLL里面出来的数据有问题。
|
|
#12 得分:0回复于: 2014-08-29 20:44:54
Delphi 好像是从 2010 开始,char,AnsiChar, widechar, string, ansistring, widestring 占用的字节不一样了~
一定要注意,如果想高版本的程序移到低版本,就要注意字符定义必需一一对应了. 就如你dll时定义了PAnsiChar, 到了调用时,也需要 是PAnsiChar而不能用 pchar |
|
|
#13 得分:1回复于: 2014-08-30 22:12:16
随便,可以不用改,PAnsiChar就对应C++里的char* |
#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封装成导出函数); |
|
#15 得分:2回复于: 2014-09-02 10:55:03
retMsg:=PAnsiChar(str1+‘-‘+str2);
str1+‘‘+str2的内容是保存在临时变量中的,这个临时变量是局部变量,离开函数的时候就被回收了. 你转成PAnsiChar的地址指向的是无效的地址,之所以有时候会是正常的是因为内存管理器没有重用这块内存的话看上去像是对的. |
|
#16 得分:0回复于: 2014-09-13 21:30:25
string换成widestring试试看
|
|
#17 得分:0回复于: 2014-09-18 13:24:42
PAnsiChar, PChar,string 都改成 WideString 试试看。
|
标签:
原文地址:http://www.cnblogs.com/westsoft/p/5921772.html