views:

81

answers:

3
+1  Q: 

Call dll function

Hi all,

I have to acces a c written dll function, prototyped as:

#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)

My Delphi code:

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;

When I run this example, the returned strings BO_From and ErrorText are empty, all other returned parameters are OK.

When I comment one of the lines out where I do the display of the returned parameters, the strings are displayed well! Stepping into the code with the debugger has similar effect. Copying all returned parameters before displaying them has no effect. The length of the returned strings is far below the declared size.

Does someone has any clue?

Thanks in advance for any help,

Cock

A: 

Without seeing the details of the dll, it is hard to say exactly what is going on. One thing, though ...

Do you need to set ErrorLength and BOLength? Usually on calls like this these are filled in with the size of the buffer on the call. That allows the dll to avoid any kind of buffer overrun. So try, setting them to 999 before making the call.

Don Dickinson
Thanks for the reply.Have tried your suggestion, problem remains...
Oops, Don you where right!I've got the problem solved now, and yes I had to set ErrorLength and BoLength in advance. Thanks Don for your advice!
+1  A: 

You've got a missing var Status: Smallint in the declaration of procedure Aaa.

Sertac Akyuz
+1  A: 

As Sertac Akyuz mentioned, you have a missing Status parameter, and since stdcall parameters are passed right-to-left (http://docwiki.embarcadero.com/RADStudio/en/Procedures_and_Functions#Calling_Conventions), any parameters declared before this missing parameter will be corrupted.

If you want the code to function on Delphi 2009+ you should also convert PChar => PAnsiChar, and Char => AnsiChar, since SizeOf(Char)=2 on Delphi 2009+.

The "far" directive is also obsolete.

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';
Dan Bartlett