我在Delphi 10.2中编写了一个小DLL,以利用Indy组件具有的FTPS功能。 从也是用Delphi 10编写的测试应用程序调用DLL可以100%完成。但是,从Delphi 6应用程序调用DLL给我在borlndmm.dll中的访问冲突。这是连接到FTP服务器的简单代码示例。
{The function in my object:}
function TQXFTP.Connect: Boolean;
begin
Result := False;
IdFTP.Host := fHost;
IdFTP.Username := fUserName;
IdFTP.Password := fPassword;
try
IdFTP.Connect;
if IdFTP.Connected then
begin
Result := True;
end;
except
on E:Exception do
begin
fErrorOccurred := True;
fErrorMessage := E.Message;
end;
end;
end;
{Code from my DLL}
function FTPConnect(Host: string;
UserName: string;
PassWord: string): string; stdcall;
var
QXFTP: TQXFTP;
begin
Result := '';
QXFTP := TQXFTP.Create;
try
QXFTP.Host := Host;
QXFTP.UserName := UserName;
QXFTP.PassWord := PassWord;
if QXFTP.Connect then
QXFTP.Disconnect;
if QXFTP.ErrorOccurred then
Result := QXFTP.ErrorMessage
else
Result := '';
finally
FreeAndNil(QXFTP);
end;
end;
exports
FTPConnect;
{Code from my D6/D10 Test App}
function FTPConnect(Host: string;
UserName: string;
PassWord: string): string; stdcall; external QXFTPDLL.dll';
procedure TfrmFTP.btnFTPConnectClick(Sender: TObject);
var
lsFTPResult: string;
begin
lsFTPResult := FTPConnect(edtHost.Text,
edtUserName.Text,
edtPassword.Text);
if lsFTPResult = '' then
ShowMessage('FTP was sucessfull')
else
ShowMessage('FTP Failed: - ' + lsFTPResult);
end;
答案 0 :(得分:3)
在导出的函数声明中用WideString替换String类型。这是唯一的方法,因为在Delphi 10.2和Delphi 6中字符串的格式和内存布局完全不同。另一方面,WideString只是Microsoft BSTR的包装,并且在所有版本的Delphi中都是相同的。
答案 1 :(得分:-1)
非常感谢大家的投入。我首先将所有字符串都更改为PChar。这消除了访问冲突,但是我仍然无法连接到我的FTP主机。我知道这肯定是一个字符串转换错误,因为即使我从Delphi 6应用程序调用DLL,也无法对DLL中的主机,用户和pwd进行硬编码,从而使我可以连接。然后,我将所有PChar变量和参数更改为WideString(如上所述),这似乎已经解决了问题。现在,我可以成功连接文件并将其复制到FTP服务器了。
答案 2 :(得分:-3)
导致问题的原因是,您设计的DLL使用了与主应用程序共享内存的方式。为此,DLL和主应用程序必须使用相同的内存管理器。
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Sharing_Memory
现在Delphi 10正在使用FastMM内存管理器,但是如果我的内存为我服务,Delphi 6仍在使用旧的Borland内存管理器。然后,这导致DLL内存管理器与主应用程序中使用的DLL管理器之间不兼容。
您可以通过使用FastMM内存管理器替换旧的Borland内存管理器来解决此问题,该管理器是开源的,可以从此处https://github.com/pleriche/FastMM4检索