DLL传入和导出是用PAnsiString 还是 PWideString 好

ilikeff8 2017-10-26 03:09:18
用delphi xe 开发一个DLL,导出部分的定义中,
因为
以前 delphi7 时,PChar 默认等于PAnsiChar
现在 xe,PChar默认等于PWideChar
由此想到一个问题,如果我这个DLL是供其他人调用,而且我并不知道他用的是什么语言开发的系统,可能是c#,java,也可能是很老的vb6 vc6 pb 开发的

我应该对外接口是用PAnsiString 还是 PWideString 好
按道理是支持宽字符的PWideString 更好点,例如以后内容有中文,unicode

是不是PAnsiString 兼容性更好点,
用PWideString 会不会接入到老系统里会出问题 ,vb6 vc6之类的有没有支持unicode字符串的类型

...全文
519 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
基本原则:动态中的函数的返回值最好为整型,其它需求皆通过传址方式传入。
  • 打赏
  • 举报
回复
引用 7 楼 ilikeff8 的回复:
[quote=引用 6 楼 DelphiGuy 的回复:] Delphi: function GetData: PChar; stdcall; var data: string; begin data := 'abc'; result :=CoTaskMemAlloc(Length(data)+1)); StrCopy(Result, data); end;
这个应该也行,但似乎不好处理什么时候释放这块内存 [/quote] 不需要手动释放,这是在windows共享堆上分配的内存,可以跨进程共享,返回的指针映射到c#的string,由.net内存管理来决定释放的时机(GC)。用StringBuilder也可以,本质是调用端预分配内存,缺点是大小固定了,DLL端控制不了。
ilikeff8 2017-10-27
  • 打赏
  • 举报
回复
Critical error detected c0000374
ilikeff8 2017-10-27
  • 打赏
  • 举报
回复
如果是返回int完全没问题
ilikeff8 2017-10-27
  • 打赏
  • 举报
回复
那我仿造delphi里之前看到过的对windows api的封装的写法,一个xxxA,一个xxxW 现在就是调用问题 DLL:

uses
  System.SysUtils,
  System.Classes;

{$R *.res}

function GetData: PAnsiChar; stdcall;
var
  data: string;
begin
  data := 'abc';
  result :=PAnsiChar(AnsiString(data));
end;

exports
   GetData;

begin
//  DLLProc := @DLLEntryPoint;
//  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
用C# 调用

        [DllImport("Project1.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
        static extern public string GetData();
        static void Main(string[] args)
        {
            string data = GetData();
            Console.WriteLine(data.ToString());
            Console.Read();
        }
发现获得result后,返回时,发生了DLL 输出了异常, critical error detected ,网上说是什么堆被破坏 而C#端直接闪退,没有任何错误提示 怎么处理
ilikeff8 2017-10-27
  • 打赏
  • 举报
回复
引用 6 楼 DelphiGuy 的回复:
Delphi: function GetData: PChar; stdcall; var data: string; begin data := 'abc'; result :=CoTaskMemAlloc(Length(data)+1)); StrCopy(Result, data); end;
这个应该也行,但似乎不好处理什么时候释放这块内存 解决了,我把返回做成了一个参数

int GetData(var data:PAnsiChar);
var
  str:string;
begin
   str:='abc';
   StringToPAnsiChar(str,data);
   
  result:=0;
end;
并且通过move

class procedure TFunctions.StringToPAnsiChar(str:string;var dest:PAnsiChar);
var
  ansiStr:AnsiString;
begin
  ansiStr:=AnsiString(str);
  Move(ansiStr[1], dest^, Length(ansiStr)+1);
end;
并且在C#端参数定义为StringBuilder data,由C#来管理内存
  • 打赏
  • 举报
回复
Delphi: function GetData: PChar; stdcall; var data: string; begin data := 'abc'; result :=CoTaskMemAlloc(Length(data)+1)); StrCopy(Result, data); end;
lyhoo163 2017-10-26
  • 打赏
  • 举报
回复
既然是XE,写代码,当然使用PWideString 好。 如果考虑兼容性,使用PAnsiChar,甚至使用pchar。总归二头不能兼得。 最好是与调用它的语言能一致起来。就旬二楼所说,搞几个版本的Dll。
  • 打赏
  • 举报
回复
如果你考虑其他语言的兼容,就不要用string,而是pchar,可以考虑相关函数提供一个ANSI版本一个UNICODE版本。

16,748

社区成员

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

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