Что-то у меня подозрение, что по человечески это невозможно... Если не так буду рад ошибиться... Суть такая: есть дллка экспортирующая класс. Написана на VC++, так что есть хидер. Необходимо импортировать этот клас в проге на делфи.
Подскажите плиз как сделть это с минимумом извратов?
Здравствуйте, depressman, Вы писали:
D>Что-то у меня подозрение, что по человечески это невозможно... Если не так буду рад ошибиться... Суть такая: есть дллка экспортирующая класс. Написана на VC++, так что есть хидер. Необходимо импортировать этот клас в проге на делфи. D>Подскажите плиз как сделть это с минимумом извратов?
Скорее всего никак. Единственный вариант — написать обертку на C++ над этой длл — либо COM-сервер, либо обычную длл, экспортирующую все публичные методы класса и конструктор/деструктор.
Здесь это неоднократно обсуждалось — пользуйся поиском.
Здравствуйте, kavlad, Вы писали:
K>Здравствуйте, depressman, Вы писали:
D>>Что-то у меня подозрение, что по человечески это невозможно... Если не так буду рад ошибиться... Суть такая: есть дллка экспортирующая класс. Написана на VC++, так что есть хидер. Необходимо импортировать этот клас в проге на делфи. D>>Подскажите плиз как сделть это с минимумом извратов?
K>Скорее всего никак. Единственный вариант — написать обертку на C++ над этой длл — либо COM-сервер, либо обычную длл, экспортирующую все публичные методы класса и конструктор/деструктор.
Здравствуйте, kavlad, Вы писали:
OAB>>а почему бы просто интерфейсы+фабрика
K>Не совсем понял
ну описываешь интерфейс, реализуешь его на сях, дальше тебе нужно поднять реализацию этого интерфейса.
можно конечто наплодить кучу экспортируемых функций, а можно предусмотреть фабрику и одну экспортируемую функцию...
Здравствуйте, Oleg A. Bachin, Вы писали:
OAB>ну описываешь интерфейс, реализуешь его на сях, дальше тебе нужно поднять реализацию этого интерфейса. OAB>можно конечто наплодить кучу экспортируемых функций, а можно предусмотреть фабрику и одну экспортируемую функцию...
Вниметельнее смотрим мое сообщение Там первым вариантом идет COM-сервер.
Здравствуйте, kavlad, Вы писали:
OAB>>ну описываешь интерфейс, реализуешь его на сях, дальше тебе нужно поднять реализацию этого интерфейса. OAB>>можно конечто наплодить кучу экспортируемых функций, а можно предусмотреть фабрику и одну экспортируемую функцию...
K>Вниметельнее смотрим мое сообщение Там первым вариантом идет COM-сервер.
потому то у меня постоянно разногласия с народом раньше выходили, пока не показал!
интерфейс — это не ком! а ком — это конечно же интерфес
ком ассоциируется с разными завязками, регистрациями, версиями, лишними тормозами и т.д, а интерфейс — это всего лишь описатель.
Здравствуйте, kavlad, Вы писали:
K>JОК. Можно подробнее или ссылку?
нет много времени чтоб подробно...
в двух словах так:
1. на сях пишешь чистый абстрактный класс = интерфейс.
2. на делфях это получается record
3. с фабрикой все понятно
4. мапишь рекорд на то что вернула фабрика и работаешь
в догонку, статья которая по ходу ниже вызывает большие сомнения.
100% заточка на борландовый VCL.
интересно узнать, если класс будет собран VC, как это будет работать?
PS. может выкрою пол-часика — нарисую сюда фишку (если еще не рисовал)
OAB>1. на сях пишешь чистый абстрактный класс = интерфейс. OAB>2. на делфях это получается record OAB>3. с фабрикой все понятно OAB>4. мапишь рекорд на то что вернула фабрика и работаешь
э-э ... а если просто перечитать исходный пост ?
OAB>в догонку, статья которая по ходу ниже вызывает большие сомнения.
какого рода сомнения ?
OAB>100% заточка на борландовый VCL. об чём речь от здесь
OAB>интересно узнать, если класс будет собран VC, как это будет работать?
там (на сайте) есть отдельная статья и просто про с (без плюсов)
Здравствуйте, Daedalus, Вы писали:
OAB>>1. на сях пишешь чистый абстрактный класс = интерфейс. OAB>>2. на делфях это получается record OAB>>3. с фабрикой все понятно OAB>>4. мапишь рекорд на то что вернула фабрика и работаешь D>э-э ... а если просто перечитать исходный пост ?
1) если просто перечитать — то есть класс в DLL скомпиленной на VC и этот класс надо заюзать в делфях.
OAB>>в догонку, статья которая по ходу ниже вызывает большие сомнения. D>какого рода сомнения ?
по поводу юзабельности пункта перечитать 1.
OAB>>100% заточка на борландовый VCL. D> об чём речь от здесь
ты вообще в курсе о четырех байтах перед Self, которые указывают на класс?
OAB>>интересно узнать, если класс будет собран VC, как это будет работать? D>там (на сайте) есть отдельная статья и просто про с (без плюсов)
а если перечитать исходный пост? какие классы на С?
мне вообщет смешно смотреть когда люди классы пытаются завернуть в функции! легче на Си++ перейти чем такой изврат писать.
тут наоборот над читым API обвертки для классов пишут!!! деградация какая-то...
Здравствуйте, Lepsik, Вы писали:
OAB>>100% заточка на борландовый VCL. OAB>>интересно узнать, если класс будет собран VC, как это будет работать?
L>я делал wrapper для VC6 dll + stl — переводил все на чиcтые struct с занятием и высвобождением памяти внутри dll
а я пиво вчера пил, но какое отношение это имеет к рассматриваемой теме? какие враперы? о враперах уже говорили! мы о маперах говорим!
чебят, чесслово, это ж неуважение не прочитав о чем идет речь вставить свои 5 коппек.
Вот такая идея родилась. В той длл-ке экспортируется кроме класса ещё и экземпляр этого класса, через который и надо работать. Так вот делаем в новой длл-ке на VC функции, выхывающие методы, и функции чтения/записи полей. После подцепляем это хозяйство как external к методам и гетерам/сетерам пропертисов аналогичного класса в Delphi. Получаем то что надо. но возникает проблема с передачей параметров. Вроде объявил и там и там функции как __cdecl/cdecl но параметры не передаются... В чем тут может быть дело подскажите?
Я понял в чем проблема, а вот как решить её вопрос остаётся открытым. Дело в том, что дэлфи при вызове методов класса передает в стэк не только параметры метода, но и ещё один параметр указатель на экземпляр класса. Вот его то и берет прога при cdecl в качестве первого параметра. При stdcall и других всё ещё хуже. Если очищать стек будет вызываемая процедура, то она не очистит его до конца, так как не считает, что параметров меньше. И в результате всё падает при stdcall.
Варианты, которые сейчас обдумываю:
— Сделать функции с переменным числом параметров (мне кажется не поможет)
— Сделать вставки на асме для изменения стека в процедуре (сейчас буду пробовать)
— Не извращатся и сделать вызов импорченой функции вместо привязки к методу (слишком просто и нудно
Собственно насчёт асма я погорячился. Там всё гораздо проще. Можно просто сдвинуть параметры на 1. То есть если есть например 2 параметра a и b то будет что-то вроде:
int __cdecl Foo(int a,int b){
a = *(&a + 1);
*(&a + 1) = *(&a + 2); // или b = *(&b + 1);
//...
}
Конечно это изврат... Но помогает.
Естественно при этом указатель на объект — экземпляр класса затирается. Но, я думаю, он используется только для this, а это мне без надобности. Хотя кто его знает .
ЗЫ А по человечески — это делать нормальные вызовы, а не замещения из импорта...
Здравствуйте, depressman, Вы писали:
D>Я понял в чем проблема, а вот как решить её вопрос остаётся открытым. Дело в том, что дэлфи при вызове методов класса передает в стэк не только параметры метода, но и ещё один параметр указатель на экземпляр класса. Вот его то и берет прога при cdecl в качестве первого параметра. При stdcall и других всё ещё хуже. Если очищать стек будет вызываемая процедура, то она не очистит его до конца, так как не считает, что параметров меньше. И в результате всё падает при stdcall.
А ты не пробовал использовать на обоих концах одинаковые конвенции?
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
DLL не может экспортировать классы в каком то нормальном виде. Она экспортирует функции. Это в VC++ добавили какие то свои навороты. Но для импорта таких классов необходим .lib файл, сделанный при сборке DLL. Он там обворачивает функции, оставляя их реализацию внутри. Т.е. без извратов вообще не обойдешся.
Прежде чем что-то советовать хотелось бы узнать, исходники DLL есть или нет? Есть ли возможность ее изменить? Если ДА, то были дельные советы по использованию ИНТЕРФЕЙСОВ! Если DLL неприкасаема, то надо думать и смотреть каким образом VC сводит вызов методов класса к вызову функций DLL. В последнем случае сразу не соображу щас) Но думаю направление не тупиковое)
Здравствуйте, depressman, Вы писали: D>Так разве __cdecl в VC и cdecl в delphi не одно и то же? А про stdcall я имел ввиду, что и там и там поменял, естественно.
Я не понял, почему вызываемая процедура думает, что параметров меньше. Ты что, полагаешь, что в VC++ this каким-то волшебным образом передается? При одинаковых конвенциях все должно быть одинаково. Причем безопаснее не пользоваться fastcall и fastthis, т.к. они могут укладывать аргументы в регистры в разном порядке. stdcall и ccall должны полностью совпадать.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Я не понял, почему вызываемая процедура думает, что параметров меньше. Ты что, полагаешь, что в VC++ this каким-то волшебным образом передается? При одинаковых конвенциях все должно быть одинаково. Причем безопаснее не пользоваться fastcall и fastthis, т.к. они могут укладывать аргументы в регистры в разном порядке. stdcall и ccall должны полностью совпадать.
В длл процедура описана как обычная процедура, а импортируется она к методу:
procedure Class.Method(a: integer; b: integer); cdecl; external'mydll.dll' name 'MethodProcedure';
При вызове метода из дэлфи кроме обычных параметров передется еще и this. Вот и получается лишний параметр. Что-то вроде:
Бред какой-то. А как ты собрался использовать обычную процедуру в качестве метода класса? Откуда она возьмет this? либо передавай его явно, декларировав ее в DLL как
Method(TMyClass* self, int a, int b)
либо ей не нужен this, тогда это статический метод и декларировать его надо в Delphi соответственно:
classprocedure Method(a, b: integer);
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Бред какой-то. А как ты собрался использовать обычную процедуру в качестве метода класса? Откуда она возьмет this? либо передавай его явно, декларировав ее в DLL как
На бред похоже. Согласен. Но так всё работает.
Ещё раз всё по порядку. В dll функция с 2 параметрами. В delphi класс. У класса метод. С двумя параметрами. А передется через стек — 3. Если привязывать импортом из dll к методу эту функцию, то вызов проходит, но парметры они воспринимают по разному. Если бы этот метод был написан в дэлфе, как метод то он бы сам извлекал наверное этот параметр и использовал его как this.
А в самой процедуре мне this и не нужен.
Здравствуйте, depressman, Вы писали: D>На бред похоже. Согласен. Но так всё работает.
Если бы все работало, ты бы сюда не писал. D>Ещё раз всё по порядку. В dll функция с 2 параметрами. В delphi класс. У класса метод. С двумя параметрами. А передется через стек — 3. Если привязывать импортом из dll к методу эту функцию, то вызов проходит, но парметры они воспринимают по разному. Если бы этот метод был написан в дэлфе, как метод то он бы сам извлекал наверное этот параметр и использовал его как this.
Конечно. D>А в самой процедуре мне this и не нужен.
Тогда зачем ты делаешь это в дельфи методом, а не процедурой?
В общем, для тебя самый дешевый способ — добавить в DLL первый параметр void * self и не парить мозг себе и окружающим.
... << RSDN@Home 1.1.4 beta 5 rev. 395>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, nik0dim, Вы писали:
D>>глянь великолепную статью с примером D>>http://rvelthuis.bei.t-online.de/articles/articles-cppobjs.htm N>Дела давно минувших дней — статья, как и сайт не доступны. Напишите, пожалуйста, позывные этой статьи, чтоб её ещё где найти.