请帮助如何将C代码转换为Delphi代码(qsBarcode)

Erw*_*wan 3 delphi dll bitmap barcode

我需要使用qsBarcode http://www.qsbarcode.de/en/index.htm的DLL文件(这里是下载链接http://www.qsbarcode.de/en/download/qsbar39.zip).该DLL将包含条形码code39的位图图像解码为字符串.

在他们的例子中只有VB和C的例子,但我需要在Delphi中使用它.这是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;
}
Run Code Online (Sandbox Code Playgroud)

这就是我尝试在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.
Run Code Online (Sandbox Code Playgroud)

当我执行此代码和调试时,hasil只包含#$11'½, 而它应该返回条形码图像中的某些字符(您可以在zip文件中获取文件图像).请帮帮我,谢谢.


最近更新:

@ 500,谢谢,我已经把stdcall

@dthorpe,谢谢,完成

实际上建议很好,我的代码应该运行良好,但我错误地把JvFilenameEdit1.text而不是JvFilenameEdit1.FileName,我的坏:)

再次感谢您的建议,所以这是工作代码:

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.
Run Code Online (Sandbox Code Playgroud)

Dav*_*nan 6

如果我是你,我会借此机会将这个函数调用包装在更像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;
Run Code Online (Sandbox Code Playgroud)

笔记:

  1. 我正在使用隐式DLL导入(使用external)而不是显式GetProcAddress.这大大减少了样板代码的数量.
  2. 我正在将C样式的整数代码错误处理转换为Delphi异常.根据你的评论,我猜测非零回报值意味着成功.旧版本的C没有布尔类型,使用0表示false,每个非零值的计算结果为true.将此映射到Delphi布尔类型的自然方法是使用LongBool.这意味着您的调用代码不需要担心错误代码.
  3. 所有与以null结尾的字符串的转换都是在一个例程中处理的,而您的调用代码再次不需要关注这种琐事.
  4. 我编写了代码,以便它可以在ANSI和Unicode版本的Delphi之间移植.

这使您的调用代码可以更清晰地读取:

procedure TForm2.Button1Click(Sender: TObject);
var
  hasil: string;
begin
  hasil := ReadCode(JvFilenameEdit1.Text);
  ShowMessage(hasil);
end;
Run Code Online (Sandbox Code Playgroud)