Вызов функции C в DLL с параметрами перечисления из Delphi

У меня есть сторонняя (Win32) DLL, написанная на C, которая предоставляет следующий интерфейс:

DLL_EXPORT typedef enum
{
  DEVICE_PCI = 1,
  DEVICE_USB = 2
} DeviceType;

DLL_EXPORT int DeviceStatus(DeviceType kind);

Я хочу назвать это из Delphi.

Как мне получить доступ к константам DeviceType в моем коде Delphi? Или, если я должен просто использовать значения 1 и 2 напрямую, какой тип Delphi мне следует использовать для параметров "DeviceType kind"? Целое число? Слово?


person dommer    schedule 15.04.2010    source источник


Ответы (3)


Обычный способ объявить интерфейс из внешней библиотеки DLL в C - предоставить его интерфейс в заголовочном файле .H. Затем, чтобы получить доступ к DLL из C, заголовочный файл .H должен быть #included в исходном коде C.

В переводе на термины Delphi вам необходимо создать файл модуля, который описывает тот же интерфейс в терминах паскаль, переводя синтаксис c в паскаль.

В вашем случае вы должны создать такой файл, как ...

unit xyzDevice;
{ XYZ device Delphi interface unit 
  translated from xyz.h by xxxxx --  Copyright (c) 2009 xxxxx
  Delphi API to libXYZ - The Free XYZ device library --- Copyright (C) 2006 yyyyy  }

interface

type
  TXyzDeviceType = integer;

const
  xyzDll = 'xyz.dll';
  XYZ_DEVICE_PCI = 1;
  XYZ_DEVICE_USB = 2;

function XyzDeviceStatus ( kind : TXyzDeviceType ) : integer; stdcall; 
   external xyzDLL; name 'DeviceStatus';

implementation
end.

И вы должны объявить это в предложении uses вашего исходного кода. И вызовите функцию следующим образом:

uses xyzDevice;

...

  case XyzDeviceStatus(XYZ_DEVICE_USB) of ...
person PA.    schedule 15.04.2010

Базовым типом по умолчанию для enum в C ++ является int (32 бита без знака). Вам необходимо определить тот же тип параметра в Delphi. Что касается пронумерованных значений, вы можете использовать жестко запрограммированные значения 1 и 2 для вызова этой функции из Delphi или использовать любую другую функцию языка Delphi (enum? Constant? Я не знаю этого языка), которая дает тот же результат.

person Alex F    schedule 15.04.2010
comment
Если вы хотите использовать его как перечисление, вы должны установить enumsize равным 4 с помощью директивы {$ MINENUMSIZE 4}. - person Remko; 15.04.2010

Конечно, вы можете использовать Integer и передавать константу напрямую, но более безопасно объявлять функцию с использованием обычного типа enum. Должно получиться так (обратите внимание на директиву MINENUMSIZE):

{$MINENUMSIZE 4}

type
  TDeviceKind = (DEVICE_PCI = 1, DEVICE_USB = 2);

function DeviceStatus(kind: TDeviceKind): Integer; stdcall; // cdecl?
person Alex    schedule 15.04.2010
comment
К сожалению, это неверно, поскольку написано, что DEVICE_PCI будет равняться 0, а не 1. Вам нужно вставить фиктивный символ, например DEVICE_UNKNOWN, для значения 0 или присвоить значение 1 первому перечислению. - person mghie; 15.04.2010
comment
@mghie хорошо заметен. Лучшим способом было бы использовать синтаксис `type TDeviceKind = (DEVICE_PCI = 1, DEVICE_USB = 2)`, добавленный в Delphi 6? См. docwiki.embarcadero.com/RADStudio/en/ - person Gerry Coll; 15.04.2010
comment
Ой. Я, должно быть, еще сплю. Фиксированный. - person Alex; 15.04.2010