-
Сергей М. © (10.06.08 19:43) [20]
> Эффекта 0
Тебе ж русским языком говорят - нет в коде в [0] никаких интерфейсов !
Там фигурирует декларация некоего С-шного класса и ф-ция, возвращающая результатом объект этого класса. Никакими "интерфейсами" там не пахнет. -
> Тыкни в место, где рассказывается об этом, а то я СОМ не
> изучал :(
>
http://www.delphikingdom.com/lyceum/seminar.asp?ID=5 -
> Тебе ж русским языком говорят - нет в коде в [0] никаких
> интерфейсов !
Я сделал без интерфейсов - не работает.
> http://www.delphikingdom.com/lyceum/seminar.asp?ID=5
Ёпть, этож сколько надо учить :( -
Сергей М. © (11.06.08 20:48) [23]
> сделал без интерфейсов - не работает
А кто тебе вообще сказал, что "это" должно работать ?
Ты пойми - COM/OLE-технология на то и существует, чтобы могли взаимодействовать между собой программные модули, созданные в разных средах разработки. И эти модули действительно взаимодействуют при посредстве механизма интерфейсов. Но в приведенном тобой коде нет ничего, что могло бы хоть как-то подтвердить, что интересующая библиотека действительно использует этот механизм. -
Вот, как объявляется в Сишном коде: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. (12.06.08 20:37) [25]Ты хоть [3] читал? Пробовал?
-
> Ты хоть [3] читал? Пробовал?
Пробывал.
Мне нужен реальный обработчик событий, те:function CSteamInterface006.FindServersNumServers(arg1: uint): int;
begin
result:=SteamFindServersNumServers(arg1);
end;
Еслиже ставить abstract, то ругается, что нельзя это писать. Как же тогда сделать обработчик? -
Хм, сделал безSteamInterface006:=CSteamInterface006.Create;
, а простоresult:=uint(SteamInterface006);
все ОК. Только вот сама программа теперь ругается:CFileSystem_Steam::Init()Failed: failed to find steam interface
+ компиллер показывает, что обработчики событий интефейсов (не в прямом смысле слова) не вомпилируются. Судя по все му, из-за этого и ошибка. -
Vga © (13.06.08 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 © (13.06.08 03:15) [29]Ах да, совсем забыл. CSteamInterface003 и CSteamDLLAppsystem001 нужно наследовать от TObject, а не TInterfacedObject. Последний как раз реализует те самые методы COM, отсутствующие в интерфейсах стима.
-
> Применительно к этим сорцам:
Спасибо, интерфейс заработал :)
Насчет СИНа - он не юзает интерфейсы, а просто смотрит, приобрете на ли игра, а это у меня уже давно реализованно ;)
Да и тем болле те сырцы - это самостоятельная ДЛЛка, а я сейчас пишу врапер к SteamEmu для перехвата обращения к файлам (как минимум). -
Vga © (13.06.08 17:49) [31]Ну он не только смотрит на купленность, но и использует SteamFS. Но в целом да, я его потому и выбрал, что он имеет минимум требований к длл-ке.