Delphi C DLL Implementation

I am trying to implement a function from a C dll. It is billed as

int DetectTransactionCode(wchar_t* wi_type, wchar_t* wi_id);

      

If declared and named it in my delphi code as

function DetectTransactionCode (var wi_type, wi_id: PWideChar): Integer;
     cdecl; external 'WiGroupDetect.dll';

procedure TForm20.Button2Click(Sender: TObject);
var witype,wi_id : widestring;
res : integer;
begin
 res := DetectTransactionCode(PWideChar(witype),PWideChar(wi_id));
 showmessage(res.tostring);
 ShowMessage(witype +' & ' +wi_id);
end;

      

I get the result, however my witype and wi_id are causing access violations.

I've also tried:

Function  DetectTransactionCode (var witype,wi_id :widestring ) : Integer cdecl;
                  external 'WiGroupDetect.dll';

procedure TForm20.Button2Click(Sender: TObject);
var witype,wi_id : widestring;
 res : integer;
begin
 res := DetectTransactionCode(witype,wi_id);
 showmessage(res.tostring);
 ShowMessage(witype +' & ' +wi_id);
end;

      

I am assuming both parameters are output parameters. The third party provided the following:

Returns 1 for success, 0 for cancellation / rejection

Note. A blocking call is returned only when: 1 - wiCode was detected, 2 - KillDetectionProcess () is called 3 - Some error or failure has occurred, or 4 - Eventually timed out (30 minutes).

Parameters: wi_type Returns the type of the retrieved marker (ie, "WIQR" for QR) on success; or "NO" on cancellation / failure. wi_id Returns the wiCode found on success; "CANCEL" upon cancellation; or with additional information about the error on failure (ie "ERROR: ...").

I tried to change the parameters to ansistring, unicodestring but still get the same problem. I suspect it has something with the var parameter, but not sure how to get around it. Any help would be appreciated.

I was given a C sample implementation for them

[DllImport("WiGroupDetect.dll", EntryPoint = "DetectTransactionCode", CallingConvention =             CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern int DetectTransactionCode([MarshalAsAttribute(UnmanagedType.LPWStr)]  StringBuilder strWITYPE, [MarshalAsAttribute(UnmanagedType.LPWStr)] StringBuilder strUID);

      

Not sure if this will change my Delphi implementation

+3


source to share


2 answers


The two parameters are of type wchar_t*

that is a pointer to a 16-bit character. This usually means a pointer to a null-wide UTF-16 array.

So, the correct translation of the presented code:

function DetectTransactionCode (wi_type, wi_id: PWideChar): Integer;
    cdecl; external 'WiGroupDetect.dll';

      



You used var

type parameters WideString

. This will match parameters that are pointers to BSTR

, which is quite different.

I accept the calling convention cdecl

, the default for every C compiler I have come across. If you have additional information that says what the function is stdcall

, so be it. But, as written in the question, it is cdecl

.

It is not clear how data flows. Are the two string parameters in or out? One of them and the other? If you're out of parameters, you need some way of knowing how to allocate a large buffer. The fact that the function does not allow the transfer of the buffer length indicates that data is being transferred. However, in this case the parameters had to be const wchar_t*

in the C code. There is a lot of ambiguity. Be aware that a function prototype does not completely define the semantics of a function.

+2


source


Thanks to David for your answers which helped. I managed to get it right. I know that if the backward line is longer than I anticipated, then there will be an error



function DetectTransactionCode (wi_type, wi_id: pwidechar): Integer;
stdcall; external 'WiGroupDetect.dll';

procedure TForm20.Button2Click(Sender: TObject);
var witype,wi_id :  widestring;
 res : integer;
begin
 setlength(witype,10);
 setlength(wi_id,100);
 res := DetectTransactionCode(pwidechar(witype),pwidechar(wi_id));
 showmessage(res.tostring);
 setlength(witype,pos(#0,witype)-1);
 setlength(wi_id,pos(#0,wi_id)-1);
 ShowMessage(trim(witype) +' & ' +trim(wi_id));
end;

      

0


source







All Articles