【问题标题】:Sending Delphi string as a parameter to DLL将 Delphi 字符串作为参数发送到 DLL
【发布时间】:2010-07-23 02:23:17
【问题描述】:

我想在 Delphi 2010 中调用一个 DLL 函数。该函数接受一个字符串并将其写入带有 USB 接口的打印机。我不知道 DLL 是用哪种语言开发的。根据文档,函数的语法是:

int WriteUSB(PBYTE pBuffer, DWORD nNumberOfBytesToWrite);

如何在 Delphi 中声明和使用我的函数?

我这样声明函数:

var
function WriteUSB(myP:pByte;n:DWORD): integer ; external 'my.dll';

我应该在声明中使用stdcall 还是cdecl

我这样调用 DLL 函数:

procedure myProc;
var 
   str : string:
begin
     str := 'AAAAAAAAAAAAAAAAAAAAA';
     WriteUSB(str,DWORD(length(tmp)));
end;

但是这段代码总是给我异常。我知道问题在于 String 是 Unicode 并且每个字符 > 1 字节。我尝试转换为不同的字符串类型(AnsiCharShortString)但失败了。

这样做的正确方法是什么?

【问题讨论】:

    标签: delphi string dll parameters


    【解决方案1】:

    几件事。首先,如果这是一个看起来像的 C 接口,那么您需要像这样声明导入:

    function WriteUSB(myP:pAnsiChar; n:DWORD): integer; cdecl; external 'my.dll';
    

    然后调用函数,需要使用 Ansi 字符串,并将其转换为 PAnsiChar,如下所示:

    procedure myProc;
    var 
       str : AnsiString;
    begin
         str := 'AAAAAAAAAAAAAAAAAAAAA';
         WriteUSB(PAnsiChar(str), length(str));
    end;
    

    (不需要强制转换为 DWORD。)如果您这样做,它应该可以正常工作而不会给您带来任何麻烦。

    【讨论】:

      【解决方案2】:

      如果您只打算使用 Ansi 字符,但如果您想使用 unicode 字符串并且 DLL/打印机会接受它们,您可以将字符串转换为 AnsiString(如前所述),您可以尝试类似 (未经测试,但我认为它通常是正确的):

      procedure myProc;
      var
        str: string;
        buff: TBytes;
      begin
        str := 'blahblahblah'; // plus additional unicode stuff
        buff := TEncoding.Default.GetBytes(str); // of TEncoding.UTF8 or... etc
        WriteUSB(@buff[0], Length(buff));
      end;
      

      不知道这是否适用于这个特定的 DLL,但它是一种更通用的方式来应对向 unicode 字符串的转变,而不必在任何地方假设(并强制转换为)AnsiString。

      【讨论】:

      • 使用TEncoding.Default在功能上与将(Unicode)String分配给AnsiString相同,即:var str: AnsiString; str := 'blah'; WriteUSB(PByte(PAnsiChar(str)), Length(str));
      • 好的,我对此并不完全确定。但是,另外,我认为在 TBytes 周围乱扔比来回转换更好,并降低了不同版本的 Delphi 和 PChar/PAnsiChar 之间混淆的风险。另外,我通常会使用 TEncoding.UTF8 而不是 .Default 但出于某种原因认为在示例中使用 .Default 更好。不知道为什么。
      • 哎呀...是的,我意识到 TEncoding 是新的,因此在以前的版本中到处都需要 ifdef,但我仍然认为 TBytes 有助于消除混乱。
      【解决方案3】:

      非常感谢所有的反馈。我通过结合您的反馈使其发挥作用。解决办法是:

      声明(我加cdecl):

      function WriteUSB( pc:pByte;n:DWORD): integer ; cdecl; external 'my.dll';
      

      还有电话:

      Procedure myProc;
      Var
          str : string;
          buff : TBytes;
      begin
          str := 'My string";
          buff := TEncoding.Default.GetBytes(str); // of TEncoding.UTF8 or... etc
                  WriteUSB(pByte(@buff[0]), Length(buff))
      
      ...
      End;
      

      我确实对瑞典语字符有一些问题,但我会解决的。现在我知道 DLL 调用是正确的。

      再次感谢所有反馈。这是一个很棒的论坛。

      BR 德尔福用户

      【讨论】:

        【解决方案4】:

        尝试在您的通话中使用 pchar 进行投射:

          WriteUSB(pchar(str),DWORD(length(tmp))); 
        

        【讨论】:

        • 这行不通。 OP 使用的是 D2010,这意味着 String 和 PChar 是 Unicode,每个字符可能超过 1 个字节。 DLL 正在寻找指向 BYTE 的指针,但没有迹象表明 DLL 函数支持 Unicode。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-17
        • 2011-06-30
        • 2011-12-27
        相关资源
        最近更新 更多