【发布时间】:2014-06-19 17:00:29
【问题描述】:
我有一个用 Delphi 2007 编写的 DLL,由于各种原因,我无法转换为在 XE6 中编译。
我在 XE6 中编写了一个调用 DLL 的小测试应用程序,这一切都很好,但是我需要将字符串数据从 DLL 传递给 exe,并且我正在使用 PCHAR 来执行此操作。 但是,事实证明,在 XE6 exe 中使用 PCHAR 有点痛苦。
我在某处读到,在 D2007 中,PCHAR 实际上是 PANSICHAR,所以我尝试使用 PANSICHAR 并调用 DLL,但它只返回一个空字符串!
我尝试过各种其他类型,例如 PWIDECHAR、String、WideString、ShortString 和 PCHAR。 PCHAR 确实返回了一些看起来像宽字符串的东西,但我不确定它是否真的是因为它在我尝试时没有强制转换:-)
所以我想知道我做错了什么?我是否从 D2007 DLL 传递了错误的类型?我应该在 XE6 中以不同的方式使用数据吗?
-- 编辑-- 好的,根据 Remy 的想法,我没有得到任何结果,所以这次我已经包含了我的代码,我相信解决方案对某人来说是显而易见的。感谢您的帮助:-)
这是用 D2007 编写的 DLL 的代码:
library mydll;
uses
SysUtils
type
TOnCommandProc = procedure(sMessage:PAnsiChar);
stdcall;
var
FOnCommandProc: TOnCommandProc = nil;
procedure SetOnCommandProc(CallbackProc: TOnCommandProc);
stdcall;
begin
FOnCommandProc := CallbackProc;
end;
procedure OnEventMessage(Data: String);
var
BuffSize: Integer;
sOut: string;
oData : PAnsiChar;
begin
sOut:=Data;
BuffSize:=SizeOf(Char)*(Length(sOut)+1);
getmem(oData, BuffSize);
FillChar(oData^,BuffSize,0);
if (Length(sOut)>0) then
begin
Move(sOut[1], PAnsiChar(oData)^, BuffSize);
FOnCommandProc(oData);
end;
end;
procedure TryTheEvent;
begin
OnEventMessage('Hello');
end;
exports
SetOnCommandProc name 'SetOnCommandProc',
TryTheEvent name 'TryTheEvent';
end.
这是用Delphi XE6编写的调用EXE代码:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TOnCommandProc = procedure(sMessage:PAnsiChar); stdcall;
procedure SetOnCommandProc(CallbackProc: TOnCommandProc; sMessage:PAnsiChar); stdcall; external 'mydll.dll';
procedure TryTheEvent; stdcall; external 'mydll.dll';
type
TForm1 = class(TForm)
Button1: TButton;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
class procedure MyOnCommandProc(sMessage:PAnsiChar); stdcall; static;
procedure OnCommand(sMessage : PAnsiChar);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
TryTheEvent;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetOnCommandProc(@MyOnCommandProc,0);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SetOnCommandProc(nil,0);
end;
class procedure TForm1.MyOnCommandProc(sMessage:PAnsiChar); stdcall;
begin
TForm1(sMessage).OnCommand(sMessage);
end;
procedure TForm1.OnCommand(sMessage :PAnsiChar);
begin
showmessage(sMessage);
end;
end.
【问题讨论】:
-
你需要出示你的代码
-
“我做错了什么?”当您不包含代码时,期望我们帮助您编写代码。当没有什么可以检查时,很难看出哪里出了问题。
-
您对
OnEventMessage的实现是不必要的复杂。可以很简单begin FOnCommandProc(PChar(Data)); end;你的问题真的很难回答,但我不能这样做,因为它已关闭,因为你不会提供代码。 -
您的代码存在多个问题。让您着迷的是函数声明不匹配。 SetOnCommandProc 的 DLL 实现有一个参数。您导入具有两个参数的函数。最重要的是,将 sMessage 转换为 TForm1 是完全错误的。这个问题实际上与 ANSI/Unicode 无关。
-
感谢大卫额外的一双眼睛!我一定是在沮丧的某个阶段无意中删除了缺少的参数:-) 但是,您能否为您的评论提供更多信息“除此之外,将 sMessage 转换为 TForm1 是完全错误的”,因为我遗漏了一些东西.. Jeremy跨度>