Нужно конвертировать VC код в Delphi - PullRequest
1 голос
/ 13 января 2010

Мне нужно вызвать файл DLL в моем коде delphi, вот фрагмент кода файла DLL Head:

#define BookInfoDLL __declspec(dllexport)

struct _BookTime
{
    unsigned char day;
    unsigned char month;
    unsigned short year;
};

struct _stBookData
{
    unsigned char encrypt;
    _BookTime bkTime;
    unsigned int  PageCount;
};

int BookInfoDLL UpdateBooks(const char * const pBookID, 
  const char cBookTypeWord, 
  const _stBookData * const pBookData, 
  const int nBookDataCounter);

Мне нужно вызвать функцию DLL "UpdateBooks" в моем коде Delphi. Как я могу преобразовать этот код в Delphi? Спасибо!

Ответы [ 3 ]

3 голосов
/ 13 января 2010

Используйте h2pas ! Хотя это инструмент freepascal, он должен создавать Delphi-совместимый код.

2 голосов
/ 13 января 2010

Фрагмент неуправляемого кода Delphi (не тестировался, но компилируется и изменяется в соответствии с предложениями в комментариях):

interface

type

  TBookTime = packed record
    day   : byte; // unsigned 8-bit  
    month : byte;
    year  : word; // unsigned 16-bit
   end;

  TBookData = packed record
    encrypt   : byte;
    bkTime    : TBookTime;
    PageCount : LongWord;   // unsigned 32-bit
  end;

  TBookDataPtr = ^TBookData;

function UpdateBooks(
           pBookID          : PChar;
           cBookTypeWord    : byte;
           pBookData        : TBookDataPtr;
           nBookDataCounter : integer
         ) : integer; stdcall; external 'dll_file_name.dll' name 'UpdateBooks';

implementation

 // ... 

end;

Простой вызов UpdateBooks(...) из кода Delphi.


Обновление: код изменен, спасибо за комментарий!

Ниже приведены фрагменты примеров звонков ...

Общие функции и константы для всех фрагментов:

// --- Test data fill utility and constants -----------------------------------

const
  BOOK_ID         = 'Test Book ID';
  BOOK_TYPE_WORD  = 'T';
  BOOK_DATA_COUNT = 5;

procedure FillTestBookData(pBookData : TBookDataPtr; iTestNum : integer);
begin
  if(pBookData = nil) then exit;

  pBookData^.encrypt := iTestNum;
  pBookData^.bkTime.day := iTestNum;
  pBookData^.bkTime.month := iTestNum;
  pBookData^.bkTime.year := 2000 + iTestNum;
  pBookData^.PageCount := iTestNum;

end;

Вызов функции в обычном стиле Delphi:

// --- Test procedure in Delphi style -----------------------------------------

procedure TestBookUpdate_DelphiStyle;
var
  bookArray   : array of TBookData;
  iBookNumber : integer;
begin

  SetLength(bookArray, BOOK_DATA_COUNT);
  try

    for iBookNumber := Low(bookArray) to High(bookArray) do begin
      FillTestBookData( @(bookArray[iBookNumber]), iBookNumber );
    end;

    UpdateBooks( 
      PChar(BOOK_ID), ord(BOOK_TYPE_WORD), 
      @(bookArray[Low(bookArray)]), BOOK_DATA_COUNT 
    );

  finally
    SetLength(bookArray, 0); // no explicit requirement to include in code
  end;

end;

Бонус: те же тестовые вызовы в стиле C и стиле Pascal: -)

// --- Test procedure in Old Delphi (plain Pascal) style ----------------------

type
  TBookDataOldArray = array[0..0] of TBookData;
  TBookDataOldArrayPtr = ^TBookDataOldArray;

// Store range checking compiler option state
{$IFOPT R+}
  {$DEFINE RANGE_CHECK_ON}
{$ENDIF}

procedure TestBookUpdate_OldDelphiStyle;
var
  bookArrayPtr : TBookDataOldArrayPtr;
  iBookNumber  : integer;
begin

  GetMem(bookArrayPtr, BOOK_DATA_COUNT*sizeof(TBookData));
  try
    // Disable range checking compiler option
    {$R-}

    for iBookNumber := 0 to BOOK_DATA_COUNT - 1 do begin
      FillTestBookData(@(bookArrayPtr^[iBookNumber]), iBookNumber);
    end;

    // Restore range checking compiler option if turned on before disabling
    {$IFDEF RANGE_CHECK_ON}{$R+}{$ENDIF}

    UpdateBooks(
      PChar(BOOK_ID), ord(BOOK_TYPE_WORD), TBookDataPtr(bookArrayPtr), BOOK_DATA_COUNT
    );

  finally
    FreeMem(bookArrayPtr);
  end;

end;

// --- Test procedure in C style ---------------------------------------------

procedure TestBookUpdate_CStyle;
var
  bookArrayPtr  : TBookDataPtr;
  curBookPtr    : TBookDataPtr;
  curBookNumber : integer;
begin

  bookArrayPtr := AllocMem( BOOK_DATA_COUNT * sizeof(TBookData) );
  try
    curBookNumber := 0;
    curBookPtr := bookArrayPtr;
    while(curBookNumber < BOOK_DATA_COUNT) do begin
      FillTestBookData( curBookPtr, curBookNumber );
      inc(curBookNumber);
      inc(curBookPtr, 1);
      // Another pointer increment solution is :
      // curBookPtr := PChar(curBookPtr) + sizeof(TBookData);
    end;

    UpdateBooks( PChar(BOOK_ID), ord(BOOK_TYPE_WORD), bookArrayPtr, BOOK_DATA_COUNT );

  finally
    FreeMem(bookArrayPtr);
  end;

end;
1 голос
/ 13 января 2010

Я закончил свое первое преобразование заголовка C вчера. Статьи и инструменты от члена TeamB Руди Велтуиса были очень, очень полезны для меня, особенно

Подводные камни конвертации

Пакет помощников по конверсии

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...