Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Проблема использования интерфейса Delphi в CBulder


Автор: SergSW 26.8.2009, 18:16
Суть такова есть класс TIMyInter реализующий мой интерфейс IMyInter. Реализация класса и код создающий экземпляр класса вынесен в DLL.
Код

IMyInter = interface(IInterface)
...
    function AddItem(iType: Integer; iX, iY: Integer): IItem; stdcall;
...

п.с. IItem так же мой интерфейс реализуемый в этой библиотеке.

На Delphi пример работает на ура вызов проходит без ошибок, но тоже самое на CBilder-e валится в AV, причём проблема именно в том что я возвращаю IItem, т.к. прочие методы рабоают и в билдере

интерфейс на Сях
Код

interface __declspec(uuid("{6854C2C5-3411-41F3-AD2B-A1666CAF33B5}")) IMyInter: public IUnknown
...
virtual IItem* __stdcall AddItem(int iType, int iX, int iY) = 0;


под отладчиком увидел интересный момент (Пример Delphi)
Код

MainF.pas.344: FObj.AddItem(FAddType, X, Y);
004816BA 8B4508           mov eax,[ebp+$08]
004816BD 50               push eax // помещаем в стек Y
004816BE 8B450C           mov eax,[ebp+$0c]
004816C1 50               push eax // помещаем в стек X
004816C2 8B45FC           mov eax,[ebp-$04]
004816C5 8B8038030000     mov eax,[eax+$00000338]
004816CB 50               push eax // помещаем в стек FAddType
004816CC 8B45FC           mov eax,[ebp-$04]
004816CF 8B8034030000     mov eax,[eax+$00000334]
004816D5 50               push eax // помещаем в стек Self
004816D6 8D55F0           lea edx,[ebp-$10]
004816D9 52               push edx // похоже что тут в стек помещается ссылка на интерфейсный объект
004816DA 8B00             mov eax,[eax]
004816DC FF503C           call dword ptr [eax+$3c]


вызов того же метода (Пример CBuilder)
Код

MainF.cpp.88: FObj->AddItem(iType, X, Y);
004025C9 FF7508           push dword ptr [ebp+$08] // помещаем в стек Y
004025CC FF750C           push dword ptr [ebp+$0c] // помещаем в стек X
004025CF FF359CE14200     push dword ptr [$0042e19c] // помещаем в стек iType
004025D5 A198E14200       mov eax,[$0042e198]
004025DA 50               push eax // помещаем в стек Self
004025DB 8B10             mov edx,[eax]
004025DD FF523C           call dword ptr [edx+$3c]

Как видно в случае с CBuilder-ом иной список параметров помещаемых в стек. При этом везде должна идти передача параметров по stdcall как добиться единообразия?

Автор: Romikgy 26.8.2009, 19:46
Цитата(SergSW @  26.8.2009,  17:16 Найти цитируемый пост)
function AddItem(iType: Integer; iX, iY: Integer): IItem; stdcall;


Цитата(SergSW @  26.8.2009,  17:16 Найти цитируемый пост)
virtual IItem* __stdcall AddItem(int iType, int iX, int iY) = 0;

а че разные вызовы? зачем виртуал в си варианте? тем более сделаный абстрактным?

Автор: SergSW 26.8.2009, 20:14
Цитата(Romikgy @  26.8.2009,  21:46 Найти цитируемый пост)
а че разные вызовы?

В чём на Ваш взгляд они разные?

Цитата(Romikgy @  26.8.2009,  21:46 Найти цитируемый пост)
зачем виртуал в си варианте? 

Насколько я помню все методы интерфейсов являются виртуальными. Т.к. все точки входов методов должны размещаться в VTM

Цитата(Romikgy @  26.8.2009,  21:46 Найти цитируемый пост)
тем более сделаный абстрактным?

это интерфейс - у него нет реализации на C

Автор: CodeMonkey 26.8.2009, 21:06
Я ничего не понимать в сях, но

Код

function AddItem(iType: Integer; iX, iY: Integer): IItem; stdcall;


Неявно трактуется как:

Код

procedure AddItem(iType: Integer; iX, iY: Integer; out Result: IItem); stdcall;


Может это поможет.

Автор: SergSW 27.8.2009, 04:36
CodeMonkey, не знал )), спасибо за совет - попробую

эх теперь бы ещё перевезти
Код

procedure AddItem(iType: Integer; iX, iY: Integer; out Result: IItem); stdcall;

на C

Автор: CodeMonkey 27.8.2009, 08:30
А откуда взялся вариант интерфейса для C++?

Автор: SergSW 27.8.2009, 08:35
Цитата(CodeMonkey @ 27.8.2009,  10:30)
А откуда взялся вариант интерфейса для C++?

простите не понял вопроса

Автор: Alexeis 27.8.2009, 09:17
Цитата(SergSW @  27.8.2009,  07:35 Найти цитируемый пост)
простите не понял вопроса 

  Был ли он сгенерирован средой или же написан самостоятельно руками.

Автор: SergSW 27.8.2009, 09:25
Цитата(Alexeis @  27.8.2009,  11:17 Найти цитируемый пост)
  Был ли он сгенерирован средой или же написан самостоятельно руками.

был написан самостоятельно - руками

Автор: Alexeis 27.8.2009, 10:00
Вот так будет правильно

Код

__interface IMyInter;
typedef System::DelphiInterface<IMyInter> _di_IMyInter;
__interface IMyInter  : public IInterface 
{
    
public:
    virtual IItem* __stdcall AddItem(int iType, int iX, int iY) = 0 ;
};


Добавлено через 1 минуту и 49 секунд
  Просто добавляешь модуль делфи в проект билдера, и билдер сам генерит совместимые хидеры.

Автор: SergSW 27.8.2009, 10:07
но будет ли он корректно работать на VS? Сомневаюсь

Автор: Romikgy 27.8.2009, 10:16
Цитата(SergSW @  27.8.2009,  03:36 Найти цитируемый пост)
procedure AddItem(iType: Integer; iX, iY: Integer; out Result: IItem); stdcall;

иль так
Код

void __stdcall AddItem(int iType, int iX, int iY, IItem *Result);

иль так
Код

void __stdcall AddItem(int iType, int iX, int iY, IItem &Result);

имхо

Автор: Alexeis 27.8.2009, 11:50
Цитата(SergSW @  27.8.2009,  09:07 Найти цитируемый пост)
но будет ли он корректно работать на VS? Сомневаюсь

  Нет конечно, нужно просто разбираться что VS понимает под словом interface.

Автор: SergSW 27.8.2009, 12:32
Romikgy, увы но не так. Видимо несовсем внимательно читали мой код. То что выпредлогаете первым в стек засунет Result, затем Y, X, Type и this(Self) а в делфи получается порядок другой Y, X, Type, this(Self), Result несмотря на то что везде стоит вызов stdcall.

Цитата(Alexeis @  27.8.2009,  13:50 Найти цитируемый пост)
 Нет конечно, нужно просто разбираться что VS понимает под словом interface.


да вроде бы это везде абстрактные классы) Проблема возникает в передачи параметров при возврате интерфейсного объекта.

Для себя решил что проще явно переделать методы

Код

function AddItem(iType: Integer; iX, iY: Integer; var ResItem: IItem): BOOL; stdcall;


по крайней мере должно везде заработать, жаль что много переписывать придётся  smile 

Автор: Alexeis 27.8.2009, 12:56
Цитата(SergSW @  27.8.2009,  11:32 Найти цитируемый пост)
да вроде бы это везде абстрактные классы)

  А кто гарантирует что структура VMT у них совпадает?

Добавлено через 32 секунды
  По идее делфи дает COM совместимые интерфейсы.

Автор: SergSW 27.8.2009, 13:01
Цитата(Alexeis @  27.8.2009,  14:56 Найти цитируемый пост)
 А кто гарантирует что структура VMT у них совпадает?


пробовал создавать интерфейсные классы на VS и использовал их в Delphi и ошибок не было)) так что похоже структуры совпадают

Вроде склассы VS спокойно используют в Delphi [http://www.citforum.ru/programming/delphi/vcpp_classes_in_delphi/]. Логично предположить обратное, что Delphi классы должны нормально работать в VS. Если конечно правильно описать интрерфейсы  smile 

Автор: CodeMonkey 27.8.2009, 13:58
Цитата(SergSW @  27.8.2009,  13:01 Найти цитируемый пост)
Вроде склассы VS спокойно используют в Delphi

Что-то у меня жуткие подозрения насчёт работоспособности такого "недокласса" - как у него, скажем, с ClassName или InstanceSize?  А как насчёт классов с множественным наследованием?

P.S. Вообще-то есть же такая штука как TLB или кто там он есть - типа, кросс-языковое описание интерфейса. Я вообще-то без понятия, но нельзя ли как-нить его создать для интерфейса? Например, File/New/Type library. Потом вбиваете свой интерфейс, а результат импортируете в другой среде.

Добавлено через 2 минуты и 39 секунд
P.S. Например, у меня получилось вот так:
Код
[
  uuid(1D040563-1194-4DF9-B6F4-935438D24A15), 
  version(1.0), 
  helpstring("TypeLib1 Library")
    
]
library TypeLib1
{

  importlib("stdole2.tlb");
  importlib("stdvcl40.dll");

  [
    uuid(9BEDB43F-0A8E-4E62-B59D-3E180F7D9E94), 
    version(1.0), 
    dual, 
    oleautomation
  ]
   interface IMyInteger: IUnknown
  {
    [
    id(0x000000C9)
    ]
     IUnknown * _stdcall Method1([in] long inX, [in] long inY );
  };

};


Насколько я понимаю - это универсальное определение, которое должен жувать любой язык, который поддерживает интерфейсы.

Добавлено через 8 минут и 15 секунд
P.P.S. А вообще-то C++ Builder понимает Delphi-вые файлы ;) Просто создайте пустой модуль с определением интерфейса и подключите его к проекту Builder-а. Всё, интерфейс можно использовать.

Автор: Alexeis 27.8.2009, 15:06
Цитата(SergSW @  27.8.2009,  12:01 Найти цитируемый пост)
Вроде склассы VS спокойно используют в Delphi 

  Наверное все же речь об интерфейсах, а не классах. Просто в Delphi класс и интерфейс это не тоже самое.

Автор: CodeMonkey 30.8.2009, 13:09
Вот http://blogs.msdn.com/oldnewthing/archive/2004/10/05/238050.aspx что-то сказано по поводу написания интерфейсов в C++.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)