Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.08.30;
Скачать: CL | DM;

Вниз

Дельфийский интерфейс для Сишных прог   Найти похожие ветки 

 
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;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.013 c
15-1246449417
@!!ex
2009-07-01 15:56
2009.08.30
Ограничить сеть Virtual Box a


15-1246520770
oxffff
2009-07-02 11:46
2009.08.30
Анонимные методы баг компилятора


15-1246451106
@!!ex
2009-07-01 16:25
2009.08.30
ЗИЛ в Германии 45 года????


2-1246613642
Гость
2009-07-03 13:34
2009.08.30
XML Парсер


15-1246515248
Лев
2009-07-02 10:14
2009.08.30
Помогите с SQL