Delphi7中使用的C++ DLL函数

3

我希望在我的Delphi 7项目中使用C++ DLL。我已经成功地在我的Delphi 7项目中调用一个DLL函数,但在另一个参数为stringbuilder的函数中出现错误。

C++函数的详细信息如下(来自DLL的头文件)。

WN_COMM_ERR WINAPI MYFUNCTION(WN_COMM_HANDLE handle, const char *command, char *answer, unsigned long maxlen, unsigned long timeout_ms, WN_ANSWER_TYPE *type);

答案类型是枚举类型:
 typedef enum {
    WN_ANSWER_ACK = '>',        // An OK frame was received
    WN_ANSWER_NACK = '!',       // An ERR frame was received
    WN_ANSWER_TOUT = 0,         // Command timed out before an answer could be received
}WN_ANSWER_TYPE;

我已经成功地在C#代码中调用了同样的函数,它可以正常工作。但是我不知道如何在Delphi7上调用它,因为答案参数是stringbuilder类型,在Delphi7中没有任何stringbuilder类型的东西。我尝试过使用Pansichar、string和pchar,但是无法获取answer类型变量的值:-

C#声明:工作

    [DllImport("wn_comm.dll", CharSet = CharSet.Unicode)]
    public static extern UInt32 MYFUNCTION(IntPtr handle, string command, StringBuilder answer, UInt32 maxlen, UInt32 timeout_ms, ref Int32 answer_type);

调用C#函数:成功

WriteNowWrapper.MYFUNCTION(this.comm_handle, command, sbAnswer, (uint)sbAnswer.Capacity, Timeout, ref answerType)

当我从我的C#应用程序调用上述代码时,成功接收了answertype和sbanswer变量的值。

Delphi7声明:不起作用

function MYFUNCTION  (handle:Longint; command:string;var answer:PAnsichar; maxlen:integer; Timeout:integer; VAR answretype:INTEGER) : longint; stdcall; external 'wn_comm.dll';

Delphi7 调用函数:无法正常工作

   MYFUNCTION(self.comm_Handle,command,answer,2,Timeout,answerType)

当我从Delphi7应用程序调用MYFUNCTION时,它成功执行并更新了整数类型参数answertype中的值,但在answer变量中我得到了空白。有人能帮我看看我做错了什么吗?

顺便提一下,http://rvelthuis.de/articles/articles-dlls.html 和 http://rvelthuis.de/articles/articles-convert.html。 - Rudy Velthuis
3个回答

1
您的Delphi函数声明不正确。您不能使用原生的Delphi类型string。而且,答案参数不是一个var参数。
声明应该是:
function MYFUNCTION(
    handle: Integer; 
    command: PAnsichar;
    answer: PAnsichar; 
    maxlen: Cardinal; 
    timeout_ms: Cardinal; 
    out answer_type: Integer
): Cardinal; stdcall; external 'wn_comm.dll';

你问题中缺少的细节是分配answer的部分。在C#代码中,你明显已经这样做了。代码大致如下:
StringBuilder sbAnswer = new StringBuilder(256);

我猜测了容量的值。在您的 Delphi 调用代码中,您需要类似的东西。

var
  handle: Integer; 
  command: AnsiString;
  answer: AnsiString;    
  timeout_ms: Integer; 
  answer_type: Integer;
  err: Integer;
....
handle := ...;
command := ...;
SetLength(answer, 256);
timeout_ms := ...;
err := MYFUNCTION(
    handle, 
    PAnsiChar(command), 
    PAnsiChar(answer), 
    Length(answer),
    timeout_ms,
    answer_type
);

1
选民是否愿意解释一下,还是这只是盲目的报复? - David Heffernan

0

我认为你的函数需要以以下形式呈现:

function MYFUNCTION(
    handle: Integer; 
    command: PAnsichar;
    answer: PAnsichar; 
    maxlen: Cardinal; 
    timeout: Cardinal; 
    out answer_type: Integer
): Cardinal; stdcall; external 'wn_comm.dll';

大多数C++函数将是cdecl,因此您可以尝试使用cdecl而不是stdcall

-1

没有访问DLL的权限,很难确定出错的原因。但是可以尝试以下方法作为开端

function WN_ExeCommandA  (handle:Longint; command: PAnsichar;var answer:PAnsichar; maxlen:integer; Timeout:integer; VAR answretype:INTEGER) : longint; stdcall; external 'wn_comm.dll';

如果我能看到WN_ANSWER_TYPE的C++定义,我就可以更好地帮助你了。

这是一个枚举类型的定义:typedef enum { WN_ANSWER_ACK = '>', // 收到了一个OK帧 WN_ANSWER_NACK = '!', // 收到了一个ERR帧 WN_ANSWER_TOUT = 0, // 命令超时,未能收到回复 } WN_ANSWER_TYPE; - Shanu Mehta
@DavidHeffernan 那什么是正确的呢?你能解释一下我应该使用什么类型的数据类型吗? - Shanu Mehta
@Pri 我在我的回答中已经解释了。 - David Heffernan
@PriyankaMehta:var 是错误的。正确的写法是 answer: PAnsiCharPAnsiChar 已经是一个指针(char *)。使用 var 会在此基础上增加一层间接引用,这是错误的。我已经发布了这个信息,再次提供链接:http://rvelthuis.de/articles/articles-convert.html#params。 - Rudy Velthuis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接