Форум: "Основная";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];
ВнизДельфийский интерфейс для Сишных прог Найти похожие ветки
← →
andreil © (2008-06-09 00:11) [0]Значит так. Пишу ДЛЛку на Дельфи, в которой присутствуют интерфейсы.
Эта библиотека юзается сторонними программами с участием интерфейсов.
Есть часть исходников этой же ДЛЛки на С++. Вот куски, касающиеся интерфейсов:class CSteamInterface006 : public CSteamInterface005
{
public:
CSteamInterface006();
~CSteamInterface006();
virtual int FindServersNumServers(unsigned int arg1);
virtual int FindServersIterateServer(int arg1, int arg2, char *szServerAddress, unsigned int uServerAddressChars);
virtual int FindServersGetErrorString();
};unsigned int _f
{
static CSteamInterface006 SteamInterface006;
return (unsigned int)&SteamInterface006;
}
Вопрос - как это переделать на Дельфи? Просто я в интерфейсах - нуб, а тут еще вопрос - получится ли солвместить Си с Дельфи?
← →
DrPass © (2008-06-09 01:22) [1]Что-то я не увидел тут никаких интерфейсов. Обычный сишный класс, разве что слово Interface в названии присутствует
← →
andreil © (2008-06-09 10:10) [2]Я в Си нуб, о чем и сказал, но мне на инглиш форуме сказали, что там именно интерфейс и в этом коде:
unsigned int _f
{
static CSteamInterface006 SteamInterface006;
return (unsigned int)&SteamInterface006;
}
идет передача Сишной программе интерфейса.
Если делать в Дельфи CSteamInterface006 классом, то нифига не работает, поскольку компилер показывает, что процедуры этого класса не собраны в ДДЛку. + если все-таки оставить его, то при вызове этого интерфейса вылазит ошибка чтения памяти :( в том районе, где ничего нету
Если же сделать именно интерфейс, то ошибка памяти есть, но в районе, где находится неизвестный код (судя по всему - основной программы)
← →
Loginov Dmitry © (2008-06-09 10:47) [3]> но мне на инглиш форуме сказали, что там именно интерфейс
> и в этом коде:
> 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%, что удасться совместить код С++ и Дельфи, однако предполагаю, что получится. Виртуальные и абстрактные методы во всех языках, поддерживающих интерфейсы, реализованы одинаково (таблица виртуальных методов имеет везде одинаковое смещение и т.д.) (это имхо, т.к. все - по памяти).
Однако я не понял, нужно ли тебе совмещать С++ и Дельфи, или же просто переписать все на Дельфи?
← →
Игорь Шевченко © (2008-06-09 11:10) [4]
> public CSteamInterface005
описание в студию
← →
jack128_ (2008-06-09 11:25) [5]
> > public CSteamInterface005
>
>
> описание в студию
>
Зуб даю, что примерно так начинается:class CSteamInterface005 : public CSteamInterface004
:-))
> Что-то я не увидел тут никаких интерфейсов.
насколько я понимаю бинарная структура интерфейсов и дельфийских и сишных классов - совпадает. главное чтоб первые три элемента VMT базового предка классов имели ссылки на AddRef/Release/QueryInterface
← →
palva © (2008-06-09 11:58) [6]На самом деле (сужу по старым версиям, новых версий не знаю) в языке С++ нет интерфейсов. Слово interface является синонимом слова class, а интерфейсом называется класс, который не содержит полей, а только виртуальные абстрактные методы. Чтобы класс вел себя как интерфейс требуется писать дополнительный код.
← →
jack128_ (2008-06-09 13:16) [7]
> На самом деле (сужу по старым версиям, новых версий не знаю)
> в языке С++ нет интерфейсов.
естественно нет. они не нужны так как
> бинарная структура интерфейсов и дельфийских и сишных классов
А вот в дельфи интерфейсы нуны, так как классы не поддерживают множественное наследование..
← →
Dimka Maslov © (2008-06-09 13:38) [8]Есть такая штука, называется COM
Сишная библиотека делается COM-сервером, в котором реализован интерфейс. Программа на дельфе - клиент, обращающийся к серверу и получающий указатель на интерфейс. И всё. Не надо использовать никаких кривых абстрактных классов и прочей мути. Если нет желания прописывать длл в реестр, то можно обойтись и без этого. Тогда сервер должен экспортировать одну нестандартную функцию создания объекта.
← →
DrPass © (2008-06-09 15:16) [9]Я ж так понимаю, у него хостовая часть приложения уже "дана свыше" и на Ц++ (собственно, и догадаться несложно, о каком приложении идет речь -Steam). А он, читая прилагаемые к ней Цплюсплюсные хедеры, пытается сочинить клиента на Delphi.
← →
andreil © (2008-06-09 17:21) [10]Я вообщето не сочиняю клиента Стима, а делаю обертку к эмулятору, что требуют несколько проектов. Протсо без этого надо изучать кучу форматов файлов, а так - все нихтяк :)
И все-бы хорошо, но игры, в которых этот эмуль рабоает, взаимодействуют только через эти интерфейсы. Если бы были просто вызовы, я бы сюда не обращался, тк заголовки всех 156функций уже переведены :)
Но эти интерфейсы.... :( Никак не могу заставить работать и все тут :(
← →
andreil © (2008-06-09 17:24) [11]
> Сишная библиотека делается COM-сервером, в котором реализован
> интерфейс. Программа на дельфе - клиент
Я вообщето пишу Дельфийскую библиотеку для Сишной проги, а не наоборот ;)
Я просто говорои, что есть часть исходников этой библиотеки на Си
← →
andreil © (2008-06-09 21:17) [12]Итак, вроде как со всем разобрался.
Но вот вопрос - как передать интерфейс?
В Сишной ДЛЛке:return (unsigned int)&SteamInterface006;
В моей ДЛЛке:SteamInterface006:=CSteamInterface006.Create;
result:=uint(@SteamInterface006);
Правильно, или надо както по-другому?
← →
Loginov Dmitry © (2008-06-09 22:30) [13]> Правильно, или надо както по-другому?
Собаку убери.
Еще: конструкции получились неравноценны. В С++ у тебя объект создается только 1 раз. А в Дельфи - при каждом вызове экспортируемой функции.
← →
Dimka Maslov © (2008-06-10 10:57) [14]
> Я вообщето пишу Дельфийскую библиотеку для Сишной проги,
> а не наоборот ;)
Тогда тем более надо библиотеку делать COM-сервером. Кстати на Delphi это сделать немного проще.
← →
andreil © (2008-06-10 15:18) [15]
> Собаку убери.
ОК
> Тогда тем более надо библиотеку делать COM-сервером. Кстати
> на Delphi это сделать немного проще.
Тыкни в место, где рассказывается об этом, а то я СОМ не изучал :(
> Еще: конструкции получились неравноценны. В С++ у тебя объект
> создается только 1 раз. А в Дельфи - при каждом вызове экспортируемой
> функции.
Может так?:if SteamInterface006=nil then
SteamInterface006:=CSteamInterface006.Create;
result:=uint(SteamInterface006);
← →
andreil © (2008-06-10 15:21) [16]Хм, все-равно ЕРРОР :(
Посмотрите, может я объявил не правильно?:CSteamInterface006 = class (CSteamInterface005)
...
CSteamInterface005 = class (CSteamInterface004)
...
CSteamInterface004 = class (CSteamInterface003)
...
CSteamInterface003 = class (TInterfacedObject)
?
← →
DrPass © (2008-06-10 16:15) [17]
> CSteamInterface003 = class (TInterfacedObject)
Скорее всего CSteamInterface003 = class (TObject)
Чего ты за слово "интерфейс" уцепился? Нет там никаких интерфейсов, не лепи их. Это просто ссылки на классы.
← →
andreil © (2008-06-10 17:07) [18]
> Скорее всего CSteamInterface003 = class (TObject)
Сделал. Эффекта 0.
Скинул полные исходники того, что наработал, может кто поможет :(
http://ifolder.ru/6925349
← →
andreil © (2008-06-10 17:11) [19]Забыл сказать. Проблемный код находится в Steam_Interface.pas (функция "function _f(cszSteamInterfaceVersion: pChar): uint; export; cdecl;").
← →
Сергей М. © (2008-06-10 19:43) [20]
> Эффекта 0
Тебе ж русским языком говорят - нет в коде в [0] никаких интерфейсов !
Там фигурирует декларация некоего С-шного класса и ф-ция, возвращающая результатом объект этого класса. Никакими "интерфейсами" там не пахнет.
← →
Amoeba © (2008-06-11 00:13) [21]
> Тыкни в место, где рассказывается об этом, а то я СОМ не
> изучал :(
>
http://www.delphikingdom.com/lyceum/seminar.asp?ID=5
← →
andreil © (2008-06-11 18:12) [22]
> Тебе ж русским языком говорят - нет в коде в [0] никаких
> интерфейсов !
Я сделал без интерфейсов - не работает.
> http://www.delphikingdom.com/lyceum/seminar.asp?ID=5
Ёпть, этож сколько надо учить :(
← →
Сергей М. © (2008-06-11 20:48) [23]
> сделал без интерфейсов - не работает
А кто тебе вообще сказал, что "это" должно работать ?
Ты пойми - COM/OLE-технология на то и существует, чтобы могли взаимодействовать между собой программные модули, созданные в разных средах разработки. И эти модули действительно взаимодействуют при посредстве механизма интерфейсов. Но в приведенном тобой коде нет ничего, что могло бы хоть как-то подтвердить, что интересующая библиотека действительно использует этот механизм.
← →
andreil © (2008-06-12 20:21) [24]Вот, как объявляется в Сишном коде:
class CSteamInterface006 : public CSteamInterface005
{..}
.....
class CSteamInterface005 : public CSteamInterface004
{..}
.....
class CSteamInterface004 : public CSteamInterface003
{..}
.....
class CSteamInterface003
{..}
Я объявляю:CSteamInterface006 = class (CSteamInterface005)
..
end;
.....
CSteamInterface005 = class (CSteamInterface004)
..
end;
.....
CSteamInterface004 = class (CSteamInterface003)
..
end;
.....
CSteamInterface003 = class (TInterfacedObject)
..
end;
В Сишном коде я там ничего про СОМ не нашел!
← →
Loginov Dmitry. (2008-06-12 20:37) [25]Ты хоть [3] читал? Пробовал?
← →
andreil © (2008-06-12 21:49) [26]
> Ты хоть [3] читал? Пробовал?
Пробывал.
Мне нужен реальный обработчик событий, те:function CSteamInterface006.FindServersNumServers(arg1: uint): int;
begin
result:=SteamFindServersNumServers(arg1);
end;
Еслиже ставить abstract, то ругается, что нельзя это писать. Как же тогда сделать обработчик?
← →
andreil © (2008-06-12 21:54) [27]Хм, сделал без
SteamInterface006:=CSteamInterface006.Create;
, а простоresult:=uint(SteamInterface006);
все ОК. Только вот сама программа теперь ругается:CFileSystem_Steam::Init()Failed: failed to find steam interface
+ компиллер показывает, что обработчики событий интефейсов (не в прямом смысле слова) не вомпилируются. Судя по все му, из-за этого и ошибка.
← →
Vga © (2008-06-13 03:11) [28]Ну во первых, это таки интерфейсы, причем бинарно идентичные COM, собственно COM-интерфейсы в плюсах так и объявляются. Но с двумя отличиями:
1) Нету стандартных COM методов QueryInterface, AddRef, Release (в С++ их нужно явно объявлять)
2) Соглашение о вызове - cdecl.
Первый пункт не дает воспользоваться дельфовыми COM-интерфейсами - избавиться от трех стандартных методов невозможно (AFAIK). Поэтому делается несколько извращенно.
Применительно к этим сорцам:
1) Необходимо в CSteamInterface* (в Delphi кстати все-таки принято вместо C использовать префикс T) и CSteamDLLAppsystem все методы объявить как virtual; cdecl;
2) Немного изменить Steam_Interface.pas:unit Steam_Interface;
interface
uses
Windows, KOL,
utils, SteamTypes, Steam_Interface_1, Steam_Interface_2, Steam_Interface_3,
Steam_Interface_4, Steam_DLLAppsystem, Steam_Misc;
function CreateInterface(cszSteamDLLAppsystemInterfaceVersion: pChar;
pError: PSteamError): Pointer; export; cdecl;
function _f(cszSteamInterfaceVersion: pChar): Pointer; cdecl;
var
SteamDLLAppsystem: CSteamDLLAppsystem001;
SteamInterface003: CSteamInterface003;
SteamInterface004: CSteamInterface004;
SteamInterface005: CSteamInterface005;
SteamInterface006: CSteamInterface006;
implementation
function CreateInterface(cszSteamDLLAppsystemInterfaceVersion: pChar;
pError: PSteamError): Pointer; export; cdecl;
begin
Log("CreateInterface SteamDLLAppsystem version:" +cszSteamDLLAppsystemInterfaceVersion+#13#10);
result:=nil;
if cszSteamDLLAppsystemInterfaceVersion="SteamDLLAppsystem001" then
begin
SteamClearError(pError);
result:=SteamDLLAppsystem;
end;
end;
function _f(cszSteamInterfaceVersion: pChar): Pointer; export; cdecl;
begin
Log("_f SteamInterface version: "+cszSteamInterfaceVersion+#13#10);
//
result:=nil;
if cszSteamInterfaceVersion="Steam003" then Result:=SteamInterface003
else if cszSteamInterfaceVersion="Steam004" then Result:=SteamInterface004
else if cszSteamInterfaceVersion="Steam005" then Result:=SteamInterface005
else if cszSteamInterfaceVersion="Steam006" then Result:=SteamInterface006
end;
initialization
SteamDLLAppsystem:=CSteamDLLAppsystem001.Create;
SteamInterface003:=CSteamInterface003.Create;
SteamInterface004:=CSteamInterface004.Create;
SteamInterface005:=CSteamInterface005.Create;
SteamInterface006:=CSteamInterface006.Create;
finalization
SteamDLLAppsystem.Free;
SteamInterface003.Free;
SteamInterface004.Free;
SteamInterface005.Free;
SteamInterface006.Free;
end.
3) Там, где ругнется компилер (один из методов ...Appsystem...) - привести к int.
После этого компилится и даже позволяет запустить распакованный Sin.
← →
Vga © (2008-06-13 03:15) [29]Ах да, совсем забыл. CSteamInterface003 и CSteamDLLAppsystem001 нужно наследовать от TObject, а не TInterfacedObject. Последний как раз реализует те самые методы COM, отсутствующие в интерфейсах стима.
← →
andreil © (2008-06-13 17:30) [30]
> Применительно к этим сорцам:
Спасибо, интерфейс заработал :)
Насчет СИНа - он не юзает интерфейсы, а просто смотрит, приобрете на ли игра, а это у меня уже давно реализованно ;)
Да и тем болле те сырцы - это самостоятельная ДЛЛка, а я сейчас пишу врапер к SteamEmu для перехвата обращения к файлам (как минимум).
← →
Vga © (2008-06-13 17:49) [31]Ну он не только смотрит на купленность, но и использует SteamFS. Но в целом да, я его потому и выбрал, что он имеет минимум требований к длл-ке.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2009.08.30;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.005 c