我必须访问一个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_From
和ErrorText
为空,所有其他返回的参数都正常。
当我评论其中一行显示返回参数时,字符串显示得很好! 使用调试器进入代码具有类似的效果。 在显示之前复制所有返回的参数无效。 返回字符串的长度远低于声明的大小。
有人有任何线索吗?
提前感谢您的帮助,
公鸡
答案 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.