Портируйте этот код C на Delphi/Lazarus

У меня есть этот код на 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, но безуспешно.

Код Delphi/Lazarus:

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) Ошибка: незаконное использование COFF Magic при чтении GLib.lib

Есть намеки?

ПРИМЕЧАНИЕ. Я только что добавил ссылку на проект Visual C++ 2010 со всеми необходимыми файлами. Фактически, я только что создал "Новый проект -> Консольное приложение Win32" (я отмечаю "пустой проект" в мастере), добавил новый файл CPP, вставил код и изменил "Свойства -> Свойства конфигурации -> Линкер" - > Включить инкрементное связывание: НЕТ ", вот и все.

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

2 ответа

Правильное объявление функций будет использовать 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 или используя собственный Delumpi TDump.exe (см. Раздел "Экспорт"), т.е. используя

tdump glib.dll

в командной строке в каталоге, где находится glib.dll.

Если имена различаются, вам придется изменить части имен внешнего объявления, например external 'Glib.dll' name '_GrfLoad';, так далее.

Еще немного информации в моей статье: Подводные камни конвертации.

Конечно, также возможно, что DLL не может найти другую DLL, от которой она зависит. Dependency Walker также расскажет вам о пропавшем импорте.

Обновить

Обратите внимание, что DLL в zip-файле, с которым вы связались, называется GrfLib.dll, а не GLib.dll. И имена действительно экспортируются как GrfLoad и т.п.

Вполне возможно, что у вас есть glib.dll в вашей системе, но он не будет содержать функции, которые вы ищете.


Также обратите внимание, что большинство людей не любят скачивать zip из неизвестного источника. Они не могут знать, что на самом деле в этом.

Это решено! Я просто изменяю декларацию с:

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

И это все. спасибо Мбо, Виктории и Руди Велтуису за помощь.

Другие вопросы по тегам