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

Вниз

Что будет если...   Найти похожие ветки 

 
Dimka Maslov ©   (2014-03-14 14:20) [0]

В некий код, написанный на сях (маздайных) передаётся указатель на интерфейс, реализованный на Delphi. Внутри сишного кода к указателю применяется dynamic_cast. Что произойдёт
а) Access Violation
б) dynamic_cast спокойно вернёт 0
в) всё будет зависеть от версий компиляторов

P.S. Сам смогу проверить только вечером, а думать уже сейчас надо.


 
Inovet ©   (2014-03-14 14:26) [1]

В Сях соответсвенно тоже будет реализован, так что должно быть NULL.


 
Dimka Maslov ©   (2014-03-14 14:30) [2]

В сях я спокойно могу проверить, реализован ли данный интерфейс через объект к.-л. класса, именно при помощи dynamic_cast. Вот я и думаю, а что произойдёт, если интерфейс будет реализован "на стороне". Мне надо что-то типа системы распознавания "свой-чужой" и не хочется во множестве объектов городить дополнительны интерфейсы, чтобы сделать это через QueryInterface


 
Dimka Maslov ©   (2014-03-14 19:08) [3]

Правильный ответ - Access Violation. Жаль. Придётся городить огород.


 
clickmaker ©   (2014-03-14 19:27) [4]

ну дык, dynamic_cast - это же часть RTTI, которую каждый язык может реализовать по-своему


 
Rouse_ ©   (2014-03-14 19:31) [5]


> Dimka Maslov ©   (14.03.14 14:20) 
> В некий код, написанный на сях (маздайных) передаётся указатель
> на интерфейс, реализованный на Delphi. Внутри сишного кода
> к указателю применяется dynamic_cast. Что произойдёт

Ничетак, а ты суров. VTable (VMT) ваще-то немного не стандартизированна. Даже в дружественном нам FPC первые 12 байт интерфейсной VMT заняты служебными полями, я уж не говорю за С++ где еще множественное наследование нужно учитывать.


 
Dimka Maslov ©   (2014-03-14 19:33) [6]

ну дык можно и проверку сделать перед тем как лезть в RTTI. Впрочем можно ещё сделать оболочку и ко всем "чужим" интерфейсам её применять.


 
Dimka Maslov ©   (2014-03-14 19:35) [7]

Или совсем уж дикий способ - таки позволять свершаться AV, перехватывать его и продолжать работу, как ни в чём не бывало...


 
Rouse_ ©   (2014-03-14 19:41) [8]


> Dimka Maslov ©   (14.03.14 19:35) [7]
> Или совсем уж дикий способ - таки позволять свершаться AV,
>  перехватывать его и продолжать работу, как ни в чём не
> бывало..

Один из наших "нанопрограммистов" уже уволенный давно, пытался найти ошибку в своем классе, в котором билась память. После полутора месяцев он добился того что смог все-же на AV и чтении определенного оффсета понять что память уже побилась. Решение проблемы тоже было изящное, как только он детектировал разрушение памяти он убивал экземпляр класса, ну а чтобы излишне не заморачиваться - в деструктор класса впихнул сразу конструктор самого себя.
Получилась эдакая "птица-феникс" возрождающаяся из пепла и не убиваемая ваще никаким образом из-за пресловутого конструктора в деструкторе.

Так что твой подход я одобряю - верной дорогой идешь :)


 
Inovet ©   (2014-03-14 19:44) [9]

> [3] Dimka Maslov ©   (14.03.14 19:08)

Так а dynamic_cast<К_Чему_Делается>?


 
Dimka Maslov ©   (2014-03-14 22:54) [10]


> Inovet ©   (14.03.14 19:44) [9]


К указателю на интерфейс, полученный модулем, написанным на си, из модуля, написанного на delphi.


> Rouse_ ©   (14.03.14 19:41) [8]


Хитро, я бы до такого не додумался. Но в моём случае, я всё же сделаю так, что все объекты, реализованные в сишном модуле будут в своём QueryInterface на определённый guid откликаться, а в дельфийском - не будут.


 
Игорь Шевченко ©   (2014-03-14 22:56) [11]

COM-серверы, написанные на Delphi, спокойно реализуют всякие интерфейсы, которые передаются в код, написанный на произвольном языке.
Может, я не в тему, но слово вставить хочется.


 
Inovet ©   (2014-03-14 23:10) [12]

> [10] Dimka Maslov ©   (14.03.14 22:54)
> К указателю на интерфейс

Там Си не Builder случаем?


 
Dimka Maslov ©   (2014-03-14 23:18) [13]


> Игорь Шевченко ©   (14.03.14 22:56) [11]


Знаю и давно этим пользуюсь для гибкого взаимодействия модулей различного происхождения, но возникла потребность отличать интерфейсы, реализованные в различных модулях.


> Inovet ©   (14.03.14 23:10) [12]


нет конечно


 
clickmaker ©   (2014-03-15 12:48) [14]

> [11] Игорь Шевченко ©   (14.03.14 22:56)
> COM-серверы, написанные на Delphi, спокойно реализуют всякие
> интерфейсы, которые передаются в код, написанный на произвольном
> языке.

ключевое слово здесь - "произвольный". dynamic_cast же - специфика плюсов


 
Inovet ©   (2014-03-15 13:25) [15]

Это получается есть нечто на Си++ и нечто с точно таким же функционалом на Делфи, и мы пытаемся кастить одно к другому. Ну... Тоже самое можно и без Си в Делфи сделать - закастим принудительно какой-нибудь TForm к TStringList, результат будет похожий.

Вообще, можно как-то с помощью магии попытаться повторить делфийскую огранизацию на Си. Только стоит ли оно того.


 
Dimka Maslov ©   (2014-03-15 15:59) [16]


> Inovet ©   (15.03.14 13:25) [15]


Нет, кастить одно к другому не надо, а надо лишь п р о в е р и т ь, что полученный указатель на интерфейс реализован в модуле, разработанном на Delphi.


 
clickmaker ©   (2014-03-15 16:22) [17]

> [16] Dimka Maslov ©   (15.03.14 15:59)

а зачем? статистику собираешь? )


 
bems ©   (2014-03-15 16:42) [18]


> надо лишь п р о в е р и т ь, что полученный указатель на
> интерфейс реализован в модуле, разработанном на Delphi

а) запросить у него ObjCastGUID: TGUID = "{CEDF24DE-80A4-447D-8C75-EB871DC121FD}" через QueryInterface
б) взять адрес реализации какого-нить метода IUnknown и загнать его в GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS or GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, ...)


 
Dimka Maslov ©   (2014-03-15 18:30) [19]


> а зачем? статистику собираешь? )


Чтобы работать с ними по разному


 
Dimka Maslov ©   (2014-03-15 18:33) [20]


>  bems ©   (15.03.14 16:42) [18]


а) Это не работает с Delphi 2009. Но именно такой способ и видится мне единственно правильным, но только на некий guid должны будут откликаться "свои", а не чужие
б) даже если я получу hinstance некоторой dll, То как тогда определить, что он написан на Delphi?


 
clickmaker ©   (2014-03-15 18:45) [21]

> [19] Dimka Maslov ©   (15.03.14 18:30)

а что ж это за предметная область такая, где логика зависит от языка dll?


 
Dimka Maslov ©   (2014-03-15 18:58) [22]


> а что ж это за предметная область такая, где логика зависит
> от языка dll?


Обработка исключений


 
Игорь Шевченко ©   (2014-03-16 11:52) [23]

У исполняемых файлов собранных на Delphi есть масса отличительных черт, например, ресурс с именем DVCLAL


 
clickmaker ©   (2014-03-16 11:54) [24]

у них еще с завидным постоянством версия линкера 2.25, наверно, еще с 3-ки или 4-ки. По крайней мере, для 32-бит


 
icWasya ©   (2014-03-17 10:38) [25]

Что произойдёт
а) Access Violation
б) dynamic_cast спокойно вернёт 0
в) всё будет зависеть от версий компиляторов

Это называется UB. То есть вариант в)
Чудес не бывает. Как будет работать dynamic_cast<A>(B)?
По некоторому смещению от B(которое зависит от компилятора и версии рантайма) считывается инвормация о типе, и сравнивается с A.
Если версия рантайма совпадает, то можно сделать однозначный вывод - является ли B наследником A. Если рантайм не совпадает, то даже при одинаковых компиляторах будет неправильный вывод.
Скорее всего "информация о типе" - это адрес таблицы виртуальных функций, который в DLL и в EXE будет разный.


 
Romkin ©   (2014-03-17 11:34) [26]


> Dimka Maslov ©   (15.03.14 18:58) [22]
> > а что ж это за предметная область такая, где логика зависит
> > от языка dll?
> Обработка исключений

Кхм. COM реализует языконезависимую обработку исключений, которую и надо использовать, а не городить свой огород.


 
Dimka Maslov ©   (2014-03-17 18:55) [27]


> icWasya ©   (17.03.14 10:38) [25]


Выкатывается AV. Я проверял.


> Romkin ©   (17.03.14 11:34) [26]


Про safecall я в курсе, но не использую СOM, у меня интерфейс - лишь абстрактный класс, указателями на объекты которого обмениваются различные части программы в рамках одного процесса. И исключения прекрасно передаются из модуля в модуль, даже при перекрёстных взаимных вызовах и спокойно отлавливаются. Единственное, что сделать нельзя - это определить тип исключения, возникшего в модуле, написанном на другом языке и выдать пользователю осмысленное сообщение. Целенаправленно городить у себя весь COM c его кучей ненужных в данном случае вещей - только снижать производительность и засорять систему.


 
bems ©   (2014-03-17 22:05) [28]


> Единственное, что сделать нельзя - это определить тип исключения,
>  возникшего в модуле, написанном на другом языке и выдать
> пользователю осмысленное сообщение

ну можно проанализировать ExceptionCode на предмет совпадения с cDelphiException, и что там еще определено в system.pas


 
bems ©   (2014-03-17 22:14) [29]

ну или сравнивать с кодом от ms 0xe06d7363


 
Dimka Maslov ©   (2014-03-17 22:38) [30]


> bems ©   (17.03.14 22:14) [29]


Пишется класс-облочка для интерфейса, в деструкторе которого определяется что а) произошло исключение б) интерфейс реализован на Delphi затем идёт запрос в дельфийский модуль "брателло, ты тут это исключеньицами кидаешся, а не объяснишь ли мне, чё там у тебя не того", на что дельфийский модуль отвечает содержимым ExceptObject. Потом дельфийское исключение перехватывается через catch(...) и бросается уже как родное сишное.


 
Romkin ©   (2014-03-18 12:58) [31]


> Единственное, что сделать нельзя - это определить тип исключения,
>  возникшего в модуле, написанном на другом языке и выдать
> пользователю осмысленное сообщение. Целенаправленно городить
> у себя весь COM c его кучей ненужных в данном случае вещей
> - только снижать производительность и засорять систему.

safecall - это не COM. Не хочешь использовать уже имеющееся - ничто не мешает сделать аналог ISupportErrorInfo и использовать.


 
bems ©   (2014-03-18 12:59) [32]


> Dimka Maslov ©   (17.03.14 22:38) [30]

ну а я тебе предлагаю не анализировать при вызове чего произошел эксцепшн, а анализировать сам эксцепшн

или как вариант в каждом (на любом языке) модуле сделать экспортируемую функцию, которая отвечает на вопрос "а не объяснишь ли мне, чё там у тебя не того". в каждом модуле эта функция имеет одинаковое имя. определяешь модуль, реализующий интерфейс и вызываешь функцию с таким именем из этого модуля


 
Romkin ©   (2014-03-18 13:14) [33]

Если под "модулем" понимается dll, то передача исключений за границы модуля чревата внезапностями с памятью.
http://www.gunsmoker.ru/2012/02/5.html#n4


 
Dimka Maslov ©   (2014-03-18 14:38) [34]


> bems ©   (18.03.14 12:59) [32]


Все исключения у меня генерируются и обрабатываются в одном модуле (назовём его центральным). Поэтому всё прекрасно работает. Другое дело, что дельфийский код может ненароком поднять своё исключение - вот тогда, хоть оно и перехватывается (нормально перехватывается и ничего никуда не утекает - fastmm стоит на страже), но нет возможности выдать нормального вида сообщение - вот тут и надо опрашивать модуль на предмет произошедшего, проблема не в том, как опрашивать, а когда надо опрашивать.


 
bems ©   (2014-03-18 16:53) [35]


> Dimka Maslov ©   (18.03.14 14:38) [34]

я же это и говорю. лан, не нравятся предложения - думай сам


 
icWasya ©   (2014-03-18 17:48) [36]

Если это COM, то в Дельфи методы скорее всего описаны как SafeCall - они не должны выбрасывать исключения.


 
Dimka Maslov ©   (2014-03-18 19:45) [37]


> icWasya ©   (18.03.14 17:48) [36]


Это я всё написал, и методы описаны как stdcall, мне важнее производительность, а не постоянная проверка кода ошибки


 
Inovet ©   (2014-03-18 21:23) [38]

Тогда я бы сходил по указателю и поискал специфические для каждого языка структуры. Т.е. кастить надо к указателю на байт.


 
Dimka Maslov ©   (2014-03-19 21:52) [39]

Сделал так: каждый объект должен реализовавать некоторый интерфейс IModuleRequest c одним методом GetModule, который возвращает hInstance своего модуля. Если интерфейс не реализован, или возвращает hInstance другого модуля, он считается "чужим" и к нему применяются все рестрикции. Да, в силу того, что в убогоих сях нельзя наследовать реализацию интерфейсов родительского объекта (большое спасиюо Борланду за TInterfacedObject и наше счастливое детство)  это потребует написания долполнительного кода, но все способы с "хождениями по указателям" кажутся мне ненадёжными или зависящими от версии среды разработки.


 
jack128_   (2014-03-19 22:17) [40]


> нельзя наследовать реализацию интерфейсов родительского
> объекта

э-э-э. В смысле?? На дельфи можешь описать что ты имеешь в виду?



Страницы: 1 2 вся ветка

Текущий архив: 2014.10.26;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.008 c
2-1383653282
Dmitry.0xDEADFA11
2013-11-05 16:08
2014.10.26
Транзакции


1-1328523971
Дмитрий
2012-02-06 14:26
2014.10.26
XE2 C++ Firemonkey stdcall - Помогите решить проблему.


15-1394643206
HITMAN
2014-03-12 20:53
2014.10.26
Помогите разработать алгоритм проверки поля в LINES


2-1383329935
dmitryl
2013-11-01 22:18
2014.10.26
dbisam


15-1394806551
7even
2014-03-14 18:15
2014.10.26
стили в firemonkey