PDA

Показать полную графическую версию : [решено] Как в С вызвать функцию из Delphi библиотеки?


mingw
01-07-2009, 13:28
В заголовочном файле (header.pas)
определен интерфейс


ControlInterface = interface
function f_check: Boolean; stdcall;
function f_user(dwType: DWORD; Proc: Pointer; User: DWORD): Boolean; stdcall;
function f_rem(dwType: DWORD; Proc: Pointer): Boolean; stdcall;
end;


Как вызвать эти функции (f_check, f_user, f_rem) из модуля написанного на C?

Как вызвать из C++ Builder я знаю. Мне же нужно вызывать из C без борланда, без плюсов.

Alan85
01-07-2009, 19:26
Т.е. Вы хотите чтобы Си "понял" Delphi на уровне исходников? или все же есть dll. C++ Builder имеет компилятор Delphi и большинство его компонентов и модулей именно на делфях сделаны поэтому понимает исходники а вот чистый си не сможет.

pva
02-07-2009, 06:52
на с++ будет выглядеть так:

typedef unsigned long DWORD;

class ControlInterface
{
public:
virtual bool __stdcall f_check() = 0;
virtual bool __stdcall f_user(DWORD dwType, void* proc, DWORD User) = 0;
virtual bool __stdcall f_rem(DWORD dwType, void* proc) = 0;
};

если коспилятор не поддерживает виртуальные функции:

typedef unsigned long DWORD;
typedef bool __stdcall (*f_check_t)();
typedef bool __stdcall (*f_user_t)(DWORD dwType, void* proc, DWORD User);
typedef bool __stdcall (*f_rem_t)(DWORD dwType, void* proc);

struct ControlInterface
{
f_check_t f_check;
f_user_t f_user;
f_rem_t f_rem;
};

// вызов:
ControlInterface* interface = GetInterface(...);
interface->f_check();

mingw
02-07-2009, 14:32
Alan85,
есть dll и заголовочный файл для неё.
И C++ Builder правильно понимает это все.
Делает что-то типа

__interface ControlInterface;
typedef System::DelphiInterface<ControlInterface> _di_ControlInterface;
__interface ControlInterface : public IInterface {
...
};


Мне же нужно вызывать функции dll из MinGW C. Ну, не "нужно" я так хочу просто.


pva, спасибо.
Кажись это работает - в структуру я попадаю, но кажись промахиваюсь мимо функций, т.к. результат немного неожиданный.
Сейчас поэкспериментирую.

И еще, я немного (я думаю, что немного) изменил объявление структуры

typedef struct ControlInterface
{
bool __stdcall (*f_check)(void);
bool __stdcall (*f_user)(DWORD dwType, void* proc, DWORD User);
bool __stdcall (*f_rem)(DWORD dwType, void* proc);
} *pControlInterface;

// вызов:
pControlInterface interface = GetInterface(...);
interface->f_check();


Вроде то же самое. По крайней мере адреса функций такие же как в Вашем варианте получаются.

pva
03-07-2009, 07:28
__interface ControlInterface;
typedef System::DelphiInterface<ControlInterface> _di_ControlInterface;
__interface ControlInterface : public IInterface {
...
};

скорее всего это класс ActiveX, у него должна быть ещё куча функций (поэтому и результат неожиданный). Покажи точное описание интерфейса (хотя бы на паскале)

mingw
04-07-2009, 02:31
Наэкспериментировал.
Первые три указателя в структуре указывают на какие-то "системные" функции. Эти "системные" функции имеют вид
@System@@IntfAddRef$qqrx45System@%DelphiInterface$t17System@IInterface%

Каждой функции в структуре передаётся первым параметром еще и указатель на указатель на структуру (в терминах C++ это this)
"указатель на указатель" не опечатка - если в паскале объявлен объект

var
o: ControlInterface;

то в С это будет

ControlInterface **o;


В результате структура выглядит так:

typedef struct ControlInterface
{
void __stdcall (*fake1)(void *);
void __stdcall (*fake2)(void *);
void __stdcall (*fake3)(void *);
bool __stdcall (*f_check)(void *This);
bool __stdcall (*f_user)(void *This, DWORD dwType, void* proc, DWORD User);
bool __stdcall (*f_rem)(void *This, DWORD dwType, void* proc);
} *pControlInterface;

// И вызов:
pControlInterface *interface = GetInterface(...);
(*interface)->f_check(interface);
(*interface)->f_check(interface, dwType, proc, User);


Как то "корявенько" получилось :-).

pva, точное описание интерфейса по этому (http://www.aimp.ru/forum/index.php?action=dlattach;topic=420.0;attach=5874) адресу. Это SDK для аудио плейера AIMP.

pva
06-07-2009, 10:11
AddRef, Release и QueryInterface - это члены класса IUnknown. Советую почитать про технологию COM - тогда станет понятней. Если не вызывать Release, то возможны проблемы с памятью, поэтому рекомендую сделать так:

typedef struct ControlInterface
{
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject);


ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);

ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);

bool __stdcall (*f_check)(void *This);
bool __stdcall (*f_user)(void *This, DWORD dwType, void* proc, DWORD User);
bool __stdcall (*f_rem)(void *This, DWORD dwType, void* proc);
} *pControlInterface;

...

// попользовались
interface->Release(my_class);

но если компилятор всё-же поддерживает виртуальные функции, то лучше не париться и сделать по-человечески:

struct ControlInterface : IUnknown
{
bool __stdcall f_check();
bool __stdcall (DWORD dwType, void* proc, DWORD User);
bool __stdcall (DWORD dwType, void* proc);
} *pControlInterface;

...

// попользовались
interface->Release();




© OSzone.net 2001-2012