Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Дельфийский интерфейс для Сишных прог [D7, WinXP]


Страницы:   1 2

andreil ©   (2008-06-09 00:11:00) 

Значит так. Пишу ДЛЛку на Дельфи, в которой присутствуют интерфейсы.
Эта библиотека юзается сторонними программами с участием интерфейсов.
Есть часть исходников этой же ДЛЛки на С++. Вот куски, касающиеся интерфейсов:
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;
}

Вопрос - как это переделать на Дельфи? Просто я в интерфейсах - нуб, а тут еще вопрос - получится ли солвместить Си с Дельфи?


Vga   (2008-06-13 17:49:00) [1]

Ну он не только смотрит на купленность, но и использует SteamFS. Но в целом да, я его потому и выбрал, что он имеет минимум требований к длл-ке.


andreil   (2008-06-13 17:30:00) [2]


> Применительно к этим сорцам:

Спасибо, интерфейс заработал :)
Насчет СИНа - он не юзает интерфейсы, а просто смотрит, приобрете на ли игра, а это у меня уже давно реализованно ;)
Да и тем болле те сырцы - это самостоятельная ДЛЛка, а я сейчас пишу врапер к SteamEmu для перехвата обращения к файлам (как минимум).


Vga   (2008-06-13 03:15:00) [3]

Ах да, совсем забыл. CSteamInterface003 и CSteamDLLAppsystem001 нужно наследовать от TObject, а не TInterfacedObject. Последний как раз реализует те самые методы COM, отсутствующие в интерфейсах стима.


Vga   (2008-06-13 03:11:00) [4]

Ну во первых, это таки интерфейсы, причем бинарно идентичные 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.


andreil   (2008-06-12 21:54:00) [5]

Хм, сделал без
SteamInterface006:=CSteamInterface006.Create;
, а просто
result:=uint(SteamInterface006);  
все ОК. Только вот сама программа теперь ругается:
CFileSystem_Steam::Init()Failed: failed to find steam interface
+ компиллер показывает, что обработчики событий интефейсов (не в прямом смысле слова) не вомпилируются. Судя по все му, из-за этого и ошибка.


andreil   (2008-06-12 21:49:00) [6]


> Ты хоть [3] читал? Пробовал?

Пробывал.
Мне нужен реальный обработчик событий, те:
function CSteamInterface006.FindServersNumServers(arg1: uint): int;
begin
 result:=SteamFindServersNumServers(arg1);
end;

Еслиже ставить abstract, то ругается, что нельзя это писать. Как же тогда сделать обработчик?


Loginov Dmitry.   (2008-06-12 20:37:00) [7]

Ты хоть [3] читал? Пробовал?


andreil   (2008-06-12 20:21:00) [8]

Вот, как объявляется в Сишном коде:
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;

В Сишном коде я там ничего про СОМ не нашел!


Сергей М.   (2008-06-11 20:48:00) [9]


> сделал без интерфейсов - не работает


А кто тебе вообще сказал, что "это" должно работать ?

Ты пойми - COM/OLE-технология на то и существует, чтобы могли взаимодействовать между собой программные модули, созданные в разных средах разработки. И эти модули действительно взаимодействуют при посредстве механизма интерфейсов. Но в приведенном тобой коде нет ничего, что могло бы хоть как-то подтвердить, что интересующая библиотека действительно использует этот механизм.


andreil   (2008-06-11 18:12:00) [10]


> Тебе ж русским языком говорят - нет в коде в [0] никаких
> интерфейсов !

Я сделал без интерфейсов - не работает.

> http://www.delphikingdom.com/lyceum/seminar.asp?ID=5

Ёпть, этож сколько надо учить :(


Amoeba   (2008-06-11 00:13:00) [11]


> Тыкни в место, где рассказывается об этом, а то я СОМ не
> изучал :(
>

http://www.delphikingdom.com/lyceum/seminar.asp?ID=5


Сергей М.   (2008-06-10 19:43:00) [12]


>  Эффекта 0


Тебе ж русскимязыком говорят - нет в коде в [0] никаких интерфейсов !
Там фигурирует декларация некоего С-шного класса и ф-ция, возвращающая результатом объект этого класса. Никакими "интерфейсами" там не пахнет.


andreil   (2008-06-10 17:11:00) [13]

Забыл сказать. Проблемный код находится в Steam_Interface.pas (функция "function _f(cszSteamInterfaceVersion: pChar): uint; export; cdecl;").


andreil   (2008-06-10 17:07:00) [14]


> Скорее всего CSteamInterface003 = class (TObject)

Сделал. Эффекта 0.
Скинул полные исходники того, что наработал, может кто поможет :(
http://ifolder.ru/6925349


DrPass   (2008-06-10 16:15:00) [15]


> CSteamInterface003 = class (TInterfacedObject)

Скорее всего CSteamInterface003 = class (TObject)
Чего ты за слово "интерфейс" уцепился? Нет там никаких интерфейсов, не лепи их. Это просто ссылки на классы.


andreil   (2008-06-10 15:21:00) [16]

Хм, все-равно ЕРРОР :(
Посмотрите, может я объявил не правильно?:
CSteamInterface006 = class (CSteamInterface005)
...
CSteamInterface005 = class (CSteamInterface004)
...
CSteamInterface004 = class (CSteamInterface003)
...
CSteamInterface003 = class (TInterfacedObject)

?


andreil   (2008-06-10 15:18:00) [17]


> Собаку убери.

ОК

> Тогда тем более надо библиотеку делать COM-сервером. Кстати
> на Delphi это сделать немного проще.

Тыкни в место, где рассказывается об этом, а то я СОМ не изучал :(

> Еще: конструкции получились неравноценны. В С++ у тебя объект
> создается только 1 раз. А в Дельфи - при каждом вызове экспортируемой
> функции.

Может так?:
if SteamInterface006=nil then
 SteamInterface006:=CSteamInterface006.Create;
     result:=uint(SteamInterface006);


Dimka Maslov   (2008-06-10 10:57:00) [18]


> Я вообщето пишу Дельфийскую библиотеку для Сишной проги,
>  а не наоборот ;)


Тогда тем более надо библиотеку делать COM-сервером. Кстати на Delphi это сделать немного проще.


Loginov Dmitry   (2008-06-09 22:30:00) [19]

> Правильно, или надо както по-другому?


Собаку убери.

Еще: конструкции получились неравноценны. В С++ у тебя объект создается только 1 раз. А в Дельфи - при каждом вызове экспортируемой функции.


andreil   (2008-06-09 21:17:00) [20]

Итак, вроде как со всем разобрался.
Но вот вопрос - как передать интерфейс?
В Сишной ДЛЛке:
return (unsigned int)&SteamInterface006;
В моей ДЛЛке:
SteamInterface006:=CSteamInterface006.Create;
     result:=uint(@SteamInterface006);

Правильно, или надо както по-другому?


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо