将此 C 代码移植到 Delphi/Lazarus

问题描述 投票:0回答:2

我有这个 C 代码,我想将其移植到 Delphi,但我无法使其工作。

.CPP代码

#include <Windows.h>

#include <io.h>
#include <stdio.h>

#include "GLibExp.h"
#pragma comment(lib, "GLib.lib")

void MyCFunc(LPCTSTR GStr)
{
    GFile GVar = NULL;
    GVar = GrfLoad(GStr, 1);
    if ( !GVar )
    {
        printf("Error during loading!\n");
    } else
        printf("All fine!\n");

    GrfFree(GVar);
    system("pause");
}

void main()
{
    CHAR StrG[MAX_PATH] = "Test.grf";
    MyCFunc(StrG);
    return;
}

GLibExp.h

#ifndef GLibExpH
#define GLibExpH

#if defined(GRF_DLL)
#define GEXPORT __declspec(dllexport)
#else
#define GEXPORT extern
#endif

class CGFILE;
typedef CGFILE* GFile;
//typedef void* GFile; //Also works like this

#ifdef __cplusplus
extern "C" {
#endif
GEXPORT GFile GrfLoad(const char *GName, unsigned char Mode = 1);
GEXPORT void GrfFree(GFile GVar);
#ifdef __cplusplus
}
#endif

#endif//GLibExpH

程序在运行时调用 DLL 以使用

GRFLoad
GRFFree
函数。我尝试将其移植到 Delphi,但没有成功。

德尔福/拉撒路代码:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

{$Link GLib.lib}

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

function GrfLoad(const fname: PChar; Modo: Boolean): Pointer; cdecl; external 'GLib.dll';

procedure TForm1.Button1Click(Sender: TObject);
var
  PVar: Pointer;
begin
  PVar:= GrfLoad(PChar('test.grf'),false);
end;

end. 

如果我注释掉

{$Link GLib.lib}
行,程序会运行,但当我调用
GRFLoad
时它总是崩溃(程序停止工作然后关闭)。如果我留在
{$Link GLib.lib}
行,程序将无法编译并报告错误:

project1.lpr(20,1) 错误:读取 GLib.lib 时出现非法 COFF Magic

有什么提示吗?

注意:我刚刚添加了一个指向 Visual C++ 2010 项目的链接,其中包含所需的所有文件。其实我只是做了一个“新建项目->Win32控制台应用程序”(我在向导中标记为“空项目”),添加一个新的CPP文件并粘贴代码,并更改“属性->配置属性->链接器- > 启用增量链接:否”,仅此而已。

https://drive.google.com/open?id=1JxW4Wra_kT8gfBda1t0WWqagzazzQVne

delphi dll external lazarus
2个回答
6
投票

函数的正确声明应使用

PAnsiChar
char
在 C 和 C++ 中始终是单字节类型):

type
  GFile = Pointer; // alternatively: GFile = THandle;

function GrfLoad(const FName: PAnsiChar; Mode: Boolean): GFile; cdecl; external 'GLib.dll' name 'GrfLoad';
procedure grfFree(GVar: GFile); cdecl; external 'GLib.dll' name 'GrfFree';

但是导出的名称很可能不是

GrfLoad
GrfFree
,而是不同的名称,例如
_GrfLoad
_GrfFree
。您可以使用 MS 的 Dependency Walker 等工具或使用 Delphi 自己的 TDump.exe(查找 Exports 部分)找出实际导出的名称,即使用

tdump glib.dll

glib.dll 所在目录的命令行上。

如果名称不同,则必须更改外部声明的名称部分,例如

external 'Glib.dll' name '_GrfLoad';
等。

我的文章中有更多信息:转换的陷阱

当然也有可能DLL找不到它所依赖的另一个DLL。 Dependency Walker 还会告诉您缺少导入的信息。

更新

请注意,您链接到的 zip 文件中的 DLL 称为 GrfLib.dll,而不是 GLib.dll。并且名称确实导出为

GrfLoad
等。

您的系统上很可能也有 glib.dll,但它不包含您正在寻找的功能。


另请注意,大多数人不喜欢从未知来源下载 zip。他们不知道里面到底是什么。


0
投票

解决了!我只是将声明更改为:

function GrfLoad(const fname: PChar; Modo: Boolean): Pointer; cdecl; external 'GLib.dll';

至:

function GrfLoad(const fname: PChar; Modo: Byte): Pointer; cdecl; external 'GLib.dll';

以及来电:

PVar:= GrfLoad(PChar('test.grf'),false);

至:

PVar:= GrfLoad(PChar('test.grf'),1);

仅此而已。感谢 Mbo、Victoria 和 Rudy Velthuis 的帮助。

© www.soinside.com 2019 - 2024. All rights reserved.