调用dll函数

时间:2010-08-09 20:23:21

标签: delphi delphi-7

我必须访问一个c写的dll函数,原型为:

#include "extcode.h"
#pragma pack(push)
#pragma pack(1)

#ifdef __cplusplus
extern "C" {
#endif

void __stdcall PSA_Send_BO(char hostname[], char BO_NumberIn[], 
    char BO_NumberOut[], int16_t *Status, char Error_text[], int32_t *Error_code, 
    int32_t *length_BO_NumberOut, int32_t *length_error_text);

long __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);

#ifdef __cplusplus
} // extern "C"
#endif

#pragma pack(pop)

我的Delphi代码:

procedure Aaa(HostNaam: PChar; BO_To: PChar; BO_From: PChar; ErrorText: PChar;
              var OutputLength: LongInt;  var ErrorLength: LongInt; 
              var ErrorNumber: Longint
              ) ; far; stdcall; external 'aaa.dll'


{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
  BO_From, ErrorText: Array[0..999] of Char;
  ErrorLength, BoLength, ErrorNumber: LongInt;
begin
  Aaa(PChar(edtHostName.Text), PChar(edtBoNumber.Text), BO_From, ErrorText, BoLength, ErrorLength, ErrorNumber);

  Label1.Caption := 'BO_From = ' + BO_From ;
  Label2.Caption := 'BoLength = ' + IntToStr(BoLength);
  Label3.Caption := 'ErrorText = ' + ErrorText; 
  Label4.Caption := 'ErrorLength = ' + IntToStr(ErrorLength);  
  Label5.Caption := 'ErrorNumber = ' + IntToStr(ErrorNumber);
end;

当我运行此示例时,返回的字符串BO_FromErrorText为空,所有其他返回的参数都正常。

当我评论其中一行显示返回参数时,字符串显示得很好! 使用调试器进入代码具有类似的效果。 在显示之前复制所有返回的参数无效。 返回字符串的长度远低于声明的大小。

有人有任何线索吗?

提前感谢您的帮助,

公鸡

3 个答案:

答案 0 :(得分:1)

var Status: Smallint声明中遗失了procedure Aaa

答案 1 :(得分:1)

正如Sertac Akyuz所提到的,你有一个缺少的Status参数,并且因为stdcall参数是从右向左传递的(http://docwiki.embarcadero.com/RADStudio/en/Procedures_and_Functions#Calling_Conventions),所以在这个缺失参数之前声明的任何参数都将被破坏。

如果您希望代码在Delphi 2009+上运行,您还应该转换PChar => PAnsiChar和Char => AnsiChar,因为Delphi 2009 +上的SizeOf(Char)= 2。

“远”指令也已过时。

procedure Aaa(HostNaam: PAnsiChar; BO_To: PAnsiChar; BO_From: PAnsiChar;
              var Status: SmallInt; ErrorText: PAnsiChar; 
              var OutputLength: LongInt;  var ErrorLength: LongInt;  
              var ErrorNumber: Longint 
              ) ; stdcall; external 'aaa.dll';

答案 2 :(得分:0)

如果没有看到dll的细节,很难确切地说出发生了什么。但有一件事......

您需要设置ErrorLength和BOLength吗?通常在这样的调用上,这些调用将填充调用缓冲区的大小。这允许dll避免任何类型的缓冲区溢出。所以尝试一下,在拨打电话之前将它们设置为999.