Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.007 c
1-1213595605
ganda
2008-06-16 09:53
2009.08.30
DevEpress Grid + фильтрация


10-1158414306
AAAA
2006-09-16 17:45
2009.08.30
TDCOMConnection. Создал


1-1212768112
San1712
2008-06-06 20:01
2009.08.30
Как передать данные в процедуру ?


2-1246014742
Лёша
2009-06-26 15:12
2009.08.30
Самоосвобождающиеся данные


15-1246342790
Холивар
2009-06-30 10:19
2009.08.30
Библиотеки DirectX





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский