-
Значит так. Пишу ДЛЛку на Дельфи, в которой присутствуют интерфейсы. Эта библиотека юзается сторонними программами с участием интерфейсов. Есть часть исходников этой же ДЛЛки на С++. Вот куски, касающиеся интерфейсов: class CSteamInterface006 : public CSteamInterface005
;
unsigned int _f
Вопрос - как это переделать на Дельфи? Просто я в интерфейсах - нуб, а тут еще вопрос - получится ли солвместить Си с Дельфи?
-
Что-то я не увидел тут никаких интерфейсов. Обычный сишный класс, разве что слово Interface в названии присутствует
-
Я в Си нуб, о чем и сказал, но мне на инглиш форуме сказали, что там именно интерфейс и в этом коде: unsigned int _f
идет передача Сишной программе интерфейса. Если делать в Дельфи CSteamInterface006 классом, то нифига не работает, поскольку компилер показывает, что процедуры этого класса не собраны в ДДЛку. + если все-таки оставить его, то при вызове этого интерфейса вылазит ошибка чтения памяти :( в том районе, где ничего нету Если же сделать именно интерфейс, то ошибка памяти есть, но в районе, где находится неизвестный код (судя по всему - основной программы)
-
> но мне на инглиш форуме сказали, что там именно интерфейс > и в этом коде: > unsigned int _f > { > static CSteamInterface006 SteamInterface006; > return (unsigned int)&SteamInterface006; > } > идет передача Сишной программе интерфейса.
Тут передается просто ссылка на созданный (причем static) объект. Причем здесь интерфейсы? Переписать - не проблема (наверно:). Один в один переписывай весь код на дельфи. В ЕХЕ тебе нужно создать аналогичный класс, только абстрактный. Например: TSteamInterface006 = class(TSteamInterface005)
public
function FindServersNumServers(arg1: Cardinal): Integer; virtual; stdcall; abstract;
function FindServersIterateServer(arg1, arg2: Integer; szServerAddress: PChar; uServerAddressChars: Integer): Integer; virtual; stdcall; abstract;
function FindServersGetErrorString(): Integer; virtual; stdcall; abstract;
end; Далее объявляешь переменную var
ASteamInterface: TSteamInterface006; Получаешь ссылку на объект: Cardinal(ASteamInterface) := _f(); И работаешь с объектом через абстрактные методы. В рельности же будут вызваны функции из DLL. Не уверен на 100%, что удасться совместить код С++ и Дельфи, однако предполагаю, что получится. Виртуальные и абстрактные методы во всех языках, поддерживающих интерфейсы, реализованы одинаково (таблица виртуальных методов имеет везде одинаковое смещение и т.д.) (это имхо, т.к. все - по памяти). Однако я не понял, нужно ли тебе совмещать С++ и Дельфи, или же просто переписать все на Дельфи?
-
> public CSteamInterface005
описание в студию
-
> > public CSteamInterface005 > > > описание в студию >
Зуб даю, что примерно так начинается: class CSteamInterface005 : public CSteamInterface004 :-)) > Что-то я не увидел тут никаких интерфейсов.
насколько я понимаю бинарная структура интерфейсов и дельфийских и сишных классов - совпадает. главное чтоб первые три элемента VMT базового предка классов имели ссылки на AddRef/Release/QueryInterface
-
На самом деле (сужу по старым версиям, новых версий не знаю) в языке С++ нет интерфейсов. Слово interface является синонимом слова class, а интерфейсом называется класс, который не содержит полей, а только виртуальные абстрактные методы. Чтобы класс вел себя как интерфейс требуется писать дополнительный код.
-
> На самом деле (сужу по старым версиям, новых версий не знаю) > в языке С++ нет интерфейсов.
естественно нет. они не нужны так как
> бинарная структура интерфейсов и дельфийских и сишных классов
А вот в дельфи интерфейсы нуны, так как классы не поддерживают множественное наследование..
-
Есть такая штука, называется COM
Сишная библиотека делается COM-сервером, в котором реализован интерфейс. Программа на дельфе - клиент, обращающийся к серверу и получающий указатель на интерфейс. И всё. Не надо использовать никаких кривых абстрактных классов и прочей мути. Если нет желания прописывать длл в реестр, то можно обойтись и без этого. Тогда сервер должен экспортировать одну нестандартную функцию создания объекта.
-
Я ж так понимаю, у него хостовая часть приложения уже "дана свыше" и на Ц++ (собственно, и догадаться несложно, о каком приложении идет речь -Steam). А он, читая прилагаемые к ней Цплюсплюсные хедеры, пытается сочинить клиента на Delphi.
-
Я вообщето не сочиняю клиента Стима, а делаю обертку к эмулятору, что требуют несколько проектов. Протсо без этого надо изучать кучу форматов файлов, а так - все нихтяк :) И все-бы хорошо, но игры, в которых этот эмуль рабоает, взаимодействуют только через эти интерфейсы. Если бы были просто вызовы, я бы сюда не обращался, тк заголовки всех 156функций уже переведены :) Но эти интерфейсы.... :( Никак не могу заставить работать и все тут :(
-
> Сишная библиотека делается COM-сервером, в котором реализован > интерфейс. Программа на дельфе - клиент
Я вообщето пишу Дельфийскую библиотеку для Сишной проги, а не наоборот ;) Я просто говорои, что есть часть исходников этой библиотеки на Си
-
Итак, вроде как со всем разобрался. Но вот вопрос - как передать интерфейс? В Сишной ДЛЛке: return (unsigned int)&SteamInterface006; В моей ДЛЛке: SteamInterface006:=CSteamInterface006.Create;
result:=uint(@SteamInterface006); Правильно, или надо както по-другому?
-
> Правильно, или надо както по-другому?
Собаку убери.
Еще: конструкции получились неравноценны. В С++ у тебя объект создается только 1 раз. А в Дельфи - при каждом вызове экспортируемой функции.
-
> Я вообщето пишу Дельфийскую библиотеку для Сишной проги, > а не наоборот ;)
Тогда тем более надо библиотеку делать COM-сервером. Кстати на Delphi это сделать немного проще.
-
> Собаку убери.
ОК > Тогда тем более надо библиотеку делать COM-сервером. Кстати > на Delphi это сделать немного проще.
Тыкни в место, где рассказывается об этом, а то я СОМ не изучал :( > Еще: конструкции получились неравноценны. В С++ у тебя объект > создается только 1 раз. А в Дельфи - при каждом вызове экспортируемой > функции.
Может так?: if SteamInterface006=nil then
SteamInterface006:=CSteamInterface006.Create;
result:=uint(SteamInterface006);
-
Хм, все-равно ЕРРОР :( Посмотрите, может я объявил не правильно?: CSteamInterface006 = class (CSteamInterface005)
...
CSteamInterface005 = class (CSteamInterface004)
...
CSteamInterface004 = class (CSteamInterface003)
...
CSteamInterface003 = class (TInterfacedObject) ?
-
> CSteamInterface003 = class (TInterfacedObject)
Скорее всего CSteamInterface003 = class (TObject) Чего ты за слово "интерфейс" уцепился? Нет там никаких интерфейсов, не лепи их. Это просто ссылки на классы.
-
> Скорее всего CSteamInterface003 = class (TObject)
Сделал. Эффекта 0. Скинул полные исходники того, что наработал, может кто поможет :( http://ifolder.ru/6925349
-
Забыл сказать. Проблемный код находится в Steam_Interface.pas (функция "function _f(cszSteamInterfaceVersion: pChar): uint; export; cdecl;").
|