Please help how to convert C code to Delphi code (qsBarcode)

I need to use the DLL file from qsBarcode http://www.qsbarcode.de/en/index.htm (here is the download link http://www.qsbarcode.de/en/download/qsbar39.zip ). The dll will decode the bitmap containing the barcode 39 into a string.

In their example, there are only examples of VB and C, but I need to use it in Delphi. here is the official code example in C:

#include <windows.h>
#include <stdio.h>

typedef int (WINAPI * CODE39_PROC)(char *, char *);

int main(int argc, char* argv[])
{
    HINSTANCE       hinstLib; 
    CODE39_PROC     ProcAdd; 
    BOOL            fFreeResult; 

    char            cFileName[512] = "\0";
    char            cResult[512] = "\0";
    int             iReturn = 0;


    if(argc < 2) return 0; //no bitmap filename in argv[1]

    strcpy(cFileName,argv[1]);

    hinstLib = LoadLibrary("qsBar39"); 
    if (hinstLib == NULL) return -1; //can't load lib

    ProcAdd = (CODE39_PROC) GetProcAddress(hinstLib, "ReadCode39"); 
    if (NULL == ProcAdd) return -1; //can't access Proc

    //dll Proc call
    iReturn = (ProcAdd) (cFileName, cResult); 
    printf("%s", cResult);

    fFreeResult = FreeLibrary(hinstLib); 

    return iReturn;
}

and this is what I'm trying to code in Delphi

unit uRead;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Mask, JvExMask, JvToolEdit;

type
  TDLLFunc = function(namafile: PChar; hasil:PChar):integer;
  TForm2 = class(TForm)
    JvFilenameEdit1: TJvFilenameEdit;
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
   DLLFunc: TDLLFunc = nil;

var
  Form2: TForm2;
  DLLHandle: THandle;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
   feedback : integer;
   hasil:PChar;
begin
   DLLHandle := LoadLibrary('qsBar39.dll');
   if (DLLHandle < HINSTANCE_ERROR) then
     raise Exception.Create('library can not be loaded or not found. ' + SysErrorMessage(GetLastError));

   try
     { load an address of required procedure}
     @DLLFunc := GetProcAddress(DLLHandle, 'ReadCode39');

     {if procedure is found in the dll}
     if Assigned(DLLFunc) then
       feedback := DLLFunc(PChar(JvFilenameEdit1.Text), PChar(hasil));
     showmessage(hasil);
   finally
     {unload a library}
     FreeLibrary(DLLHandle);
   end;

end;

end.

When I execute this code and debug, hasil contains only # $ 11'½ while it should return some character in the barcode image (you can get the image of the file in a zip file). Please help me, thanks.


:

@500, , stdcall

@dthorpe, ,

, , JvFilenameEdit1.text JvFilenameEdit1.FileName, bad:)

, :

unit uRead;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Mask, JvExMask, JvToolEdit;

type
  TDLLFunc = function(namafile: PAnsiChar; hasil:PAnsiChar):integer; stdcall;
  TForm2 = class(TForm)
    JvFilenameEdit1: TJvFilenameEdit;
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
   DLLFunc: TDLLFunc = nil;

var
  Form2: TForm2;
  DLLHandle: THandle;

implementation

{$R *.dfm}

procedure TForm2.Button1Click(Sender: TObject);
var
   feedback : integer;
   hasil: array [0..512] of char;
begin
   DLLHandle := LoadLibrary('qsBar39.dll');
   if (DLLHandle < HINSTANCE_ERROR) then
     raise Exception.Create('library can not be loaded or not found. ' + SysErrorMessage(GetLastError));

   try
     { load an address of required procedure}
     @DLLFunc := GetProcAddress(DLLHandle, 'ReadCode39');

     {if procedure is found in the dll}
     if Assigned(DLLFunc) then
        feedback := DLLFunc(PAnsiChar(JvFilenameEdit1.FileName), @hasil);

     edit1.Text := StrPas(@hasil);

   finally
     {unload a library}
     FreeLibrary(DLLHandle);
   end;

end;

end.
+3
3

, , Delphi-.

function ReadCode39(FileName, Result: PAnsiChar): LongBool; stdcall;
  external 'qsBar39';

function ReadCode(const FileName: string): string;
var
  cResult: array [0..512-1] of AnsiChar;
begin
  if not ReadCode39(PAnsiChar(AnsiString(FileName)), @cResult[0]) then
    raise Exception.Create('ReadCode39 failed');
  Result := string(cResult);
end;

:

  • DLL ( external), GetProcAddress. .
  • C Delphi. , , . C 0 false, . Delphi LongBool. , .
  • , .
  • , ANSI Unicode Delphi.

:

procedure TForm2.Button1Click(Sender: TObject);
var
  hasil: string;
begin
  hasil := ReadCode(JvFilenameEdit1.Text);
  ShowMessage(hasil);
end;
+6

stdcall; TDLLFunc, , WINAPI, , , Delphi Unicode, , , PAnsiChar.

+3

In addition to the stdcall mentioned in another answer, you also need to allocate space for the pchar pointers that you pass to the DLLFunc. Note that in C code, cResult var is defined as char cResult[512];This means that the caller reserves a space for a char buffer of 512 characters and passes the address of this buffer to the DLL function.

You are not making an equivalent in your Delphi code.

Modify your Delphi code to define hasil as a char array:

var hasil: array [0..512] of char;

then pass the hasil address to the DLLFunc call:

DLLFunc(PChar(JvFilenameEdit1.Text), @hasil);
+2
source

All Articles