从Delphi 6调用时,用Delphi 10编写的DLL提供了访问冲突。

时间:2018-10-30 10:36:46

标签: delphi

我在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;

3 个答案:

答案 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检索