Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Как в С вызвать функцию из Delphi библиотеки? (http://forum.oszone.net/showthread.php?t=143916)

mingw 01-07-2009 13:28 1156343

Как в С вызвать функцию из Delphi библиотеки?
 
В заголовочном файле (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 1156649

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

pva 02-07-2009 06:52 1156932

на с++ будет выглядеть так:
Код:

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 1157296

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 1157848

Код:

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

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

mingw 04-07-2009 02:31 1158641

Наэкспериментировал.
Первые три указателя в структуре указывают на какие-то "системные" функции. Эти "системные" функции имеют вид
@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, точное описание интерфейса по этому адресу. Это SDK для аудио плейера AIMP.

pva 06-07-2009 10:11 1159931

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



Время: 14:27.

Время: 14:27.
© OSzone.net 2001-