Re: DLL и <dynamic_cast>
От: Centaur Россия  
Дата: 09.09.09 03:22
Оценка: -3 :))
Здравствуйте, Frostyland, Вы писали:

F>В DLL создается некий объект класса и возвращается по базовому указателю вызывающей стороне.

F>На стороне вызова я пытаюсь возвести базовый указатель к ожидаемому типу при помощи dynamic_cast, но получаю NULL.
F>Причем, как DLL так и приложение собрано с одним и тем же файлом, описывающим оба класса (класс и суперкласс),
F>соответственно, взаимосвязь типов должна быть известна RTTI.
F>Или не так? Нельзя так делать?

Объекты классов (кроме POD) нельзя передавать через границу DLL.
Re[4]: MFC::CString знаешь? ;)
От: Erop Россия  
Дата: 09.09.09 16:29
Оценка: +2 :)
Здравствуйте, Centaur, Вы писали:

C>DLL должна позволять использовать её из модуля, написанного на любом языке и скомпилированного любым компилятором.


Да: И как заюзать DLL из спектрумовского пролога, гоняемого под эмулятором?
Ergo: Существование DLL вообще недопустимо...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re: DLL и <dynamic_cast>
От: Chorkov Россия  
Дата: 08.09.09 07:52
Оценка: -1
Здравствуйте, Frostyland, Вы писали:

F>Здравствуйте.

F>В DLL создается некий объект класса и возвращается по базовому указателю вызывающей стороне.
F>На стороне вызова я пытаюсь возвести базовый указатель к ожидаемому типу при помощи dynamic_cast, но получаю NULL.
F>Причем, как DLL так и приложение собрано с одним и тем же файлом, описывающим оба класса (класс и суперкласс),
F>соответственно, взаимосвязь типов должна быть известна RTTI.
F>Или не так? Нельзя так делать?

F>С уважением, ВВК



Стандарт не специфицирует протокол передачи информации между модулями, однако, при аккуратном обращении, приведение классов по dynamic_cast обычно доступно.

Какой компилятор ты используешь?

Как ты экспортируешь классы из DLL?
Если по __declspec(dllexport/dllimport), то проверь что проэкспортированы оба класса.
Если класс объявлен без __declspec-а (и определен в обоих модулях) то это будут как бы два независимых класса.
Re[2]: DLL и <dynamic_cast>
От: MasterZiv СССР  
Дата: 09.09.09 09:49
Оценка: +1
Centaur пишет:

> Объекты классов (кроме POD) нельзя передавать через границу DLL.


Это -- всего лишь расхожее заблуждение.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: MFC::CString знаешь? ;)
От: Centaur Россия  
Дата: 09.09.09 12:53
Оценка: :)
Здравствуйте, Erop, Вы писали:

C>>Объекты классов (кроме POD) нельзя передавать через границу DLL.

E>Да? Тебе не кажется, что это, как минимум, зависит от компилятора? Хорошо бы указать для какого компилятора верно твоё утверждение...

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

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

Указатели на объекты можно передавать через границу DLL, но только как непрозрачные хэндлы. То есть единственное, что могут сделать с этим хэндлом с другой стороны — это сохранить и когда-нибудь передать обратно.
Re[4]: MFC::CString знаешь? ;)
От: MasterZiv СССР  
Дата: 09.09.09 15:39
Оценка: +1
Centaur пишет:


> DLL должна позволять использовать её из модуля, написанного на любом

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

Это может быть требованием к DLL, а может и не быть.
Ты, блин, экстремист какой-то. А если мне не нужно работать с этой
DLL из любого языка программирования ? На кой фиг мне себя ограничивать ?

> Все попытки передать объект через интерфейс DLL ведут к более сильному

> связыванию (coupling) между DLL и клиентом. В частности, их придётся
> компилировать одним и тем же компилятором с одними и теми же ключами и
> соблюдать ещё массу компилятороспецифичных ограничений. Которые могут
> быть и не задокументированы.

Ну, скомпилируй, в чём проблема ?

> Указатели на объекты можно передавать через границу DLL, но только как

> непрозрачные хэндлы. То есть единственное, что могут сделать с этим
> хэндлом с другой стороны — это сохранить и когда-нибудь передать обратно.

В общем, этот подход очень ограничительный. Да, в проектировании библиотек
с C-шным API только так и можно делать. Но зачем весь в мире код
писать как библиотеки с C-шным API ? Ты же не каждый день usr32.dll пишешь.
Posted via RSDN NNTP Server 2.1 beta
Re[6]: MFC::CString знаешь? ;)
От: MasterZiv СССР  
Дата: 09.09.09 16:53
Оценка: +1
Nik_1 пишет:

> а зачем тогда вообще что-то выносить в длл, а не статически линковать?


А зачем тогда вообще DLL ?

Вот для всего того, для чего нужны DLL, за минусом кроссязыковости.
Posted via RSDN NNTP Server 2.1 beta
DLL и <dynamic_cast>
От: Frostyland  
Дата: 08.09.09 06:50
Оценка:
Здравствуйте.
В DLL создается некий объект класса и возвращается по базовому указателю вызывающей стороне.
На стороне вызова я пытаюсь возвести базовый указатель к ожидаемому типу при помощи dynamic_cast, но получаю NULL.
Причем, как DLL так и приложение собрано с одним и тем же файлом, описывающим оба класса (класс и суперкласс),
соответственно, взаимосвязь типов должна быть известна RTTI.
Или не так? Нельзя так делать?

С уважением, ВВК
С уважением, В.Куликов
Re[2]: DLL и <dynamic_cast>
От: MasterZiv СССР  
Дата: 08.09.09 15:01
Оценка:
Chorkov пишет:

> Как ты экспортируешь классы из DLL?

> Если по __declspec(dllexport/dllimport), то проверь что
> проэкспортированы оба класса.
> Если класс объявлен без __declspec-а (и определен в обоих модулях) то
> это будут как бы два независимых класса.

Ну и все модули должны быть с RTTI собраны. Это правда наверное очевидно.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: DLL и <dynamic_cast>
От: Programador  
Дата: 08.09.09 16:55
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Ну и все модули должны быть с RTTI собраны. Это правда наверное очевидно.


Они работают возможно на основании неких ID которые скорее всего адреса vtabl. А в разных сборках vtabl разные Qt говорит что их каст работает всегда ( для QObject ) и в dll в отличии от обычных
Re: DLL и <dynamic_cast>
От: Erop Россия  
Дата: 08.09.09 17:05
Оценка:
Здравствуйте, Frostyland, Вы писали:

F>соответственно, взаимосвязь типов должна быть известна RTTI.

F>Или не так? Нельзя так делать?

Какой таки компилятор? Если DLL, то наверное MSVC?
В MSVC RTTI работает на основе ИМЁН классов, так что твоя схема РАБОТОСПОСОБНА.

попробуй собрать минимальный пример?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: DLL и <dynamic_cast>
От: byleas  
Дата: 08.09.09 20:18
Оценка:
Здравствуйте, Erop, Вы писали:

E>В MSVC RTTI работает на основе ИМЁН классов, так что твоя схема РАБОТОСПОСОБНА.

А vtable генерится в вызывающем модуле при использовании класса?
Re[3]: DLL и <dynamic_cast>
От: Erop Россия  
Дата: 09.09.09 01:31
Оценка:
Здравствуйте, byleas, Вы писали:

B>А vtable генерится в вызывающем модуле при использовании класса?

Ну ты же к нему dyn_cast делаешь? По идее должна генериться...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: MFC::CString знаешь? ;)
От: Erop Россия  
Дата: 09.09.09 04:00
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Объекты классов (кроме POD) нельзя передавать через границу DLL.

Да? Тебе не кажется, что это, как минимум, зависит от компилятора? Хорошо бы указать для какого компилятора верно твоё утверждение...

Для MSVC это не так. Смотри MFC, например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: DLL и <dynamic_cast>
От: Pavel Dvorkin Россия  
Дата: 09.09.09 05:28
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, byleas, Вы писали:


B>>А vtable генерится в вызывающем модуле при использовании класса?

E>Ну ты же к нему dyn_cast делаешь? По идее должна генериться...

Все нормально работает

DLL:
class _declspec(dllexport) C
{
public:
    virtual void f(void) { return;}
};
class _declspec(dllexport) D : public C
{
public:
    virtual void g() { return;}
};
__declspec(dllexport) C* getD()
{
    return new D;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    return TRUE;
}


EXE


class _declspec(dllimport) C
{
public:
    virtual void f(void);
};
class _declspec(dllimport) D : public C
{
public:
    virtual void g();
};
__declspec(dllexport) C* getD();

__declspec(dllimport) void* getC();
int _tmain(int argc, _TCHAR* argv[])
{
    C* pcEXE = new D;
    D* pdEXE = dynamic_cast<D*>(pcEXE);
    C* pcDLL = getD();
    D* pdDLL = dynamic_cast<D*>(pcDLL);
    return 0;
}


Все указатели ненулевые.
With best regards
Pavel Dvorkin
Re: DLL и <dynamic_cast>
От: Frostyland  
Дата: 09.09.09 06:00
Оценка:
Здравствуйте, Frostyland, Вы писали:

Отвечаю сразу всем. Спасибо за советы и комментарии.
Компилятор от Borland C++ Builder v.6

А косяк оказался в наследовании моего базового класса от TObject — суперкласса всех классов VCL.
Как только я убрал это наследование — все заработало.
Привем, при наследовании от него таблица экспортный функций экспортировала и vtable

LIBRARY     MY_DLL.DLL

EXPORTS
    @$xp$8TDllBase                 @4   ; __tpdsc__ TDllBase
    @$xp$8TDllBase                 @8   ; __tpdsc__ TDllBase
    @$xp$9TDllInner                @10  ; __tpdsc__ TDllInner
    @$xp$9TDllInner                @6   ; __tpdsc__ TDllInner
    @@Dll_class@Finalize           @13  ; __linkproc__ Dll_class::Finalize
    @@Dll_class@Initialize         @12  ; __linkproc__ Dll_class::Initialize
    @TDllBase@                     @15  ; TDllBase::
    @TDllBase@                     @17  ; TDllBase::
    @TDllBase@$bctr$qv             @3   ; TDllBase::TDllBase()
    @TDllBase@$bdtr$qqrv           @9   ; __fastcall TDllBase::~TDllBase()
    @TDllBase@$bdtr$qqrv           @5   ; __fastcall TDllBase::~TDllBase()
    @TDllInner@                    @16  ; TDllInner::
    @TDllInner@                    @18  ; TDllInner::
    @TDllInner@$bctr$qv            @2   ; TDllInner::TDllInner()
    @TDllInner@$bdtr$qqrv          @11  ; __fastcall TDllInner::~TDllInner()
    @TDllInner@$bdtr$qqrv          @7   ; __fastcall TDllInner::~TDllInner()
    _GetClass                      @1   ; _GetClass
    ___CPPdebugHook                @14  ; ___CPPdebugHook



а без него, нет
LIBRARY     MY_DLL.DLL

EXPORTS
    @@Dll_class@Finalize           @7   ; __linkproc__ Dll_class::Finalize
    @@Dll_class@Initialize         @6   ; __linkproc__ Dll_class::Initialize
    @TDllBase@$bctr$qv             @3   ; TDllBase::TDllBase()
    @TDllBase@$bdtr$qqrv           @4   ; __fastcall TDllBase::~TDllBase()
    @TDllInner@$bctr$qv            @2   ; TDllInner::TDllInner()
    @TDllInner@$bdtr$qqrv          @5   ; __fastcall TDllInner::~TDllInner()
    _GetClass                      @1   ; _GetClass
    ___CPPdebugHook                @8   ; ___CPPdebugHook



Значит, компилятор BCB коряво работает с экспортными vtable


С уважением, ВВК
С уважением, В.Куликов
Re[5]: DLL и <dynamic_cast>
От: byleas  
Дата: 09.09.09 08:08
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Все нормально работает

А если без declspec?
Re[4]: MFC::CString знаешь? ;)
От: alsemm Россия  
Дата: 09.09.09 13:37
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Здравствуйте, Erop, Вы писали:


C>>>Объекты классов (кроме POD) нельзя передавать через границу DLL.

E>>Да? Тебе не кажется, что это, как минимум, зависит от компилятора? Хорошо бы указать для какого компилятора верно твоё утверждение...

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

Согласен.

C>Все попытки передать объект через интерфейс DLL ведут к более сильному связыванию (coupling) между DLL и клиентом. В частности, их придётся компилировать одним и тем же компилятором с одними и теми же ключами и соблюдать ещё массу компилятороспецифичных ограничений. Которые могут быть и не задокументированы.

Бред.

C>Указатели на объекты можно передавать через границу DLL, но только как непрозрачные хэндлы. То есть единственное, что могут сделать с этим хэндлом с другой стороны — это сохранить и когда-нибудь передать обратно.

Бред 2.

Binary-compatible C++ Interfaces — http://chadaustin.me/cppinterface.html

Про RTTI — его конечно нельзя использовать для классов в dll (в общем случае), т.к. реализация compiler specific
Re[5]: MFC::CString знаешь? ;)
От: Nik_1 Россия  
Дата: 09.09.09 15:54
Оценка:
а зачем тогда вообще что-то выносить в длл, а не статически линковать? Если делается длл — то уже подразумевается что она может существовать отдельно от экзешника(т.е. например, поставляться отдельно). И тогда вполне могут всплыть проблемы из-за разных компиляторов.
Re[6]: MFC::CString знаешь? ;)
От: Erop Россия  
Дата: 09.09.09 16:27
Оценка:
Здравствуйте, Nik_1, Вы писали:

N_>а зачем тогда вообще что-то выносить в длл, а не статически линковать? Если делается длл — то уже подразумевается что она может существовать отдельно от экзешника(т.е. например, поставляться отдельно). И тогда вполне могут всплыть проблемы из-за разных компиляторов.


например, чтобы доустанавливать её за деньги...
Или, чтобы облегчить её переиспользование в рамках боьшой конторы...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[7]: MFC::CString знаешь? ;)
От: Nik_1 Россия  
Дата: 09.09.09 16:39
Оценка:
Здравствуйте, Erop, Вы писали:
E>например, чтобы доустанавливать её за деньги...
E>Или, чтобы облегчить её переиспользование в рамках боьшой конторы...

ну дык и я отом же говорю это нужно когда длл может поставляться отдельно от exe, или использоваться в разных приложениях. Но вот тут какраз есть риск что они будут однажды собраны разными компиляторами или с разными настройками.
Re[8]: MFC::CString знаешь? ;)
От: Erop Россия  
Дата: 09.09.09 17:39
Оценка:
Здравствуйте, Nik_1, Вы писали:

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


Ну есть же всякие версии там, манифесты, то сё...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: DLL и <dynamic_cast>
От: Tonal- Россия www.promsoft.ru
Дата: 10.09.09 04:51
Оценка:
Здравствуйте, Frostyland, Вы писали:
F>Отвечаю сразу всем. Спасибо за советы и комментарии.
F>Компилятор от Borland C++ Builder v.6

F>А косяк оказался в наследовании моего базового класса от TObject — суперкласса всех классов VCL.

F>Как только я убрал это наследование — все заработало.
Наследники от TObject должны жить не в dll-ках, а в пакетах.
У багланда есть специальные механизмы под это заточенные.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[6]: DLL и <dynamic_cast>
От: Pavel Dvorkin Россия  
Дата: 10.09.09 06:33
Оценка:
Здравствуйте, byleas, Вы писали:

B>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>Все нормально работает

B>А если без declspec?

А тогда непонятно, что ты хочешь. Класс в DLL, но он не экспортируемый. Ты хочешь из EXE получить доступ к неэкспортируемым объектам DLL ? Для простых типов это возможно, но очень нехорошо. А для классов — откуда на стороне EXE возьмут реализацию всех методов класса ?
With best regards
Pavel Dvorkin
Re[7]: DLL и <dynamic_cast>
От: Erop Россия  
Дата: 10.09.09 11:01
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А тогда непонятно, что ты хочешь. Класс в DLL, но он не экспортируемый. Ты хочешь из EXE получить доступ к неэкспортируемым объектам DLL ? Для простых типов это возможно, но очень нехорошо. А для классов — откуда на стороне EXE возьмут реализацию всех методов класса ?


Ну, например, он может быть шаблонным...

А ещё может быть такой код:
if( dynamic_cast<class_from_dll*>( obj ) != 0 ) {
    cout << "Bingo!!!";
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: DLL и <dynamic_cast>
От: Pavel Dvorkin Россия  
Дата: 10.09.09 11:15
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Pavel Dvorkin, Вы писали:


PD>>А тогда непонятно, что ты хочешь. Класс в DLL, но он не экспортируемый. Ты хочешь из EXE получить доступ к неэкспортируемым объектам DLL ? Для простых типов это возможно, но очень нехорошо. А для классов — откуда на стороне EXE возьмут реализацию всех методов класса ?


E>Ну, например, он может быть шаблонным...


А что, у нас уже шаблоны в рантайме появились ? Каая мне разница, шаблонный он или нет ?

И подумай еще вот над чем. Если класс экспортируется, то в DLL его дефиниция, а в EXE его декларация. Так что на эапе линковки (через .lib то есть) произойдет связывание их. А если он не экспортируется, то изволь дефиницию делать в EXE. И никто мне в таком случае не мешает завести в EXE класс с тем же именем, но совершенно иным содержанием. Дальнейшее, думаю, понятно.



E>А ещё может быть такой код:
if( dynamic_cast<class_from_dll*>( obj ) != 0 ) {
E>    cout << "Bingo!!!";
E>}


cout << "Ух!!!";
With best regards
Pavel Dvorkin
Re[9]: DLL и <dynamic_cast>
От: Erop Россия  
Дата: 10.09.09 11:31
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А что, у нас уже шаблоны в рантайме появились ? Каая мне разница, шаблонный он или нет ?

В MSVC шаблоны не экспортируются вроде бы...

PD>И никто мне в таком случае не мешает завести в EXE класс с тем же именем, но совершенно иным содержанием. Дальнейшее, думаю, понятно.


Это будет нарушением ODR...

Тем не менее рассмотри, например, такой код:
struct X {
    std::string Text;
};

У неё есть конструктор и деструктор. И, тем не менее, её можно написать в разделяемом Dll и Exe хедере и всё таки будет хорошо...


E>>А ещё может быть такой код:
if( dynamic_cast<class_from_dll*>( obj ) != 0 ) {
E>>    cout << "Bingo!!!";
E>>}


PD> cout << "Ух!!!";

Ну и тем не менее, это валидный код, который ДОЛЖЕН РАБОТАТЬ!!!
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: DLL и <dynamic_cast>
От: Pavel Dvorkin Россия  
Дата: 10.09.09 12:15
Оценка:
Здравствуйте, Erop, Вы писали:

PD>>И никто мне в таком случае не мешает завести в EXE класс с тем же именем, но совершенно иным содержанием. Дальнейшее, думаю, понятно.


E>Это будет нарушением ODR...


Это не будет никаким вообще нарушением. Если класс внутренний для DLL (не экспортируемый), то он вообще не есть публичный символ, и я могу при разработке EXE его наличие не учитывать. Соответственно имею право давать именам моих классов какие хочу и о внутренних классах DLL не ндумать, тем более, что я и знать-то не могу, какие они там есть...

E>Тем не менее рассмотри, например, такой код:
struct X {
E>    std::string Text;
E>};

E>У неё есть конструктор и деструктор. И, тем не менее, её можно написать в разделяемом Dll и Exe хедере и всё таки будет хорошо...

Поясни. что в таком случае будет означать "разделяемый Dll и Exe хедере" ? Если то, что в обих случаях будет #include "X.h" — то это ровно ничего не значит. В DLL создается свой класс, в EXE — свой.

Представь себе, что в DLL есть

struct Y {
std::string Text;
int Value;
};

а в EXE — твой X. Хедеры хоть общие , хоть нет — разные совсем классы. Теперь мне во время разработки захотелось из Y это Value выкинуть, а Y переименовать в X. И что ?

E>>>А ещё может быть такой код:
if( dynamic_cast<class_from_dll*>( obj ) != 0 ) {
E>>>    cout << "Bingo!!!";
E>>>}


PD>> cout << "Ух!!!";

E> Ну и тем не менее, это валидный код, который ДОЛЖЕН РАБОТАТЬ!!!

Я так и не понял, откуда тип class_from_dll* взялся без экспорта.
With best regards
Pavel Dvorkin
Re[11]: DLL и <dynamic_cast>
От: Erop Россия  
Дата: 10.09.09 12:28
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

E>>Это будет нарушением ODR...


PD>Это не будет никаким вообще нарушением. Если класс внутренний для DLL (не экспортируемый), то он вообще не есть публичный символ, и я могу при разработке EXE его наличие не учитывать. Соответственно имею право давать именам моих классов какие хочу и о внутренних классах DLL не ндумать, тем более, что я и знать-то не могу, какие они там есть...


В стандарте никаких DLL нет. Есть "программа"... То, что некоторые реализации позволяют прятать часть классов в DLL, фактически вводя связывание промежуточное между внутренним и внешним, это просто особенность этих реализаций...

PD>Поясни. что в таком случае будет означать "разделяемый Dll и Exe хедере" ? Если то, что в обих случаях будет #include "X.h" — то это ровно ничего не значит. В DLL создается свой класс, в EXE — свой.


Значит то, что я могу, например, передать экземпляр этого класса из DLL в EXE, или наоборот... МОгу передать указатель и звать методы, могу работать с полями...


PD>Я так и не понял, откуда тип class_from_dll* взялся без экспорта.

Из хедера...

Экспорт класса всего лишь делает доступным снаружи DLL методы класса...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[12]: DLL и <dynamic_cast>
От: Pavel Dvorkin Россия  
Дата: 10.09.09 13:03
Оценка:
Здравствуйте, Erop, Вы писали:

E>В стандарте никаких DLL нет. Есть "программа"...


Нет. Есть компилируемая и собираемая единица (EXE, DLL). Они независимы вообще-то, так что стандарт применяй к каждой из них. И есть нестандартное расширение — экспорт, и в отношении его действуют правила MS, а не стандарта.

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


А то, что некоторые указатели на классы можно получать вызовом системных функций (COM) — это как в стандарте описано ?


E>Значит то, что я могу, например, передать экземпляр этого класса из DLL в EXE, или наоборот... МОгу передать указатель и звать методы, могу работать с полями...


ИМХО это недопустимо.


PD>>Я так и не понял, откуда тип class_from_dll* взялся без экспорта.

E>Из хедера...

E>Экспорт класса всего лишь делает доступным снаружи DLL методы класса...


Не согласен.
With best regards
Pavel Dvorkin
Re[13]: Приводи примеры реализаций, где ты прав...
От: Erop Россия  
Дата: 10.09.09 18:35
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

E>>В стандарте никаких DLL нет. Есть "программа"...

PD>Нет.
Чего? Покажи мне место в стандарте, где есть термин DLL, пожалуйста. Всюду вроде используется термин programme...
Ну там well formed programme, ill formed programme... Не встерчал?
Кстати, programme без функции main она того, ill formed... Как это, по твоему, вяжется с DLL?

PD>Есть компилируемая и собираемая единица (EXE, DLL).

А как эта "собираемая единица" называется в стандарте? Я давно читал, конечно, лет пять назад, может с тех пор что-то переписали. Но тогда я встречал термин "programme" и термин "translation unit", что ли... А как называется "собираемая единица" я даже и представить не могу. "assembling unit"?

PD>Они независимы вообще-то, так что стандарт применяй к каждой из них. И есть нестандартное расширение — экспорт, и в отношении его действуют правила MS, а не стандарта.

Да? Правда? И где в DLL функция main? Когда она получает управление? В какой взаимосвязи с этой функцией находятся конструкторы и деструкторы глобальных объектов?

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


PD>А то, что некоторые указатели на классы можно получать вызовом системных функций (COM) — это как в стандарте описано ?


Никак не описано. И DLL и COM и многопоточность -- это расширения стандарта. Он не накладывает на реализацию никаких ограничений по этому поводу. Но реализация сама может накладывать на себя ограничения и давать свои гарантии...

E>>Значит то, что я могу, например, передать экземпляр этого класса из DLL в EXE, или наоборот... МОгу передать указатель и звать методы, могу работать с полями...

PD>ИМХО это недопустимо.

Э-э-э. Я бы ещё понял, "AFAIK", но "IMHO"? При чём тут YHO? Тут, IMHO, намного важнее HO авторов реализации
Я знаю как это сделано на нескольких платформах в нескольких реализациях (SO, Dll, ShLb, оверлеи...)
И везде такое можно... Не затруднит привести реализацию, в которой нельзя?..


PD>>>Я так и не понял, откуда тип class_from_dll* взялся без экспорта.

E>>Из хедера...

E>>Экспорт класса всего лишь делает доступным снаружи DLL методы класса...

PD>Не согласен.
Ну это зависит от реализации, конечно, но это так в MSVC и в MWCW. А вот в SO'шках GCC по умолчанию экспортируется вообще всё. Они в этом смысле намного более похожи на .lib'ы...

Но в известных мне реализациях экспорт класса ничего мистического не делает. Просто экспортирует из DLL/ShLb(из SO по умолчанию всё экспортируют, так что экспорт в явном виде не нужен) методы и статические поля класса...



Но если вернуться к нашему вопросу, что будет, если я в DLL опишу класс одним образом, а в EXE другим, и передам указатель на экземпляр такого класса из DLL в EXE или обратно, то я хотел бы заметить, что С++ так спроектирован, что классы всё равно идентифицируются именно по имени. И именно для того, чтобы не было накладок и требуется, чтобы соблюдалось ODR. А так, нет проблем его нарушить. Смотри:
// shared.h
class SharedClass;
SharedClass* GetHaredClass();
// 1.cpp
#include<shared.h>
class SharedClass {
public:
    int Field1;
    int Field2;
    int Field3;
};

static SharedClass sc;
SharedClass* GetHaredClass() { return &sc; }

// 2.cpp
#include<shared.h>
class SharedClass {
public:
    const char* Ptr() const { return text.c_str(); }
private:
    std::string text;
};

const char* illFormed()
{
    return GetHaredClass()->Ptr();
}
Эта программа будет одинаково некорректна вне зависимости раскидаешь ты 1.cpp и 2.cpp по разным DLL или нет.
И некорректна она будет именно потому, что нарушено ODR...
От реалтзации и раскиданности 1.cpp и 2.cpp по разным DLL зависит только то, сможет ли транслятор заметить нарушение ODR на стадии трансляции или нет. И только...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[14]: Приводи примеры реализаций, где ты прав...
От: Pavel Dvorkin Россия  
Дата: 11.09.09 04:56
Оценка:
Здравствуйте, Erop, Вы писали:

E>Здравствуйте, Pavel Dvorkin, Вы писали:


E>>>В стандарте никаких DLL нет. Есть "программа"...

PD>>Нет.
E>Чего? Покажи мне место в стандарте, где есть термин DLL, пожалуйста. Всюду вроде используется термин programme...

Не покажу. Нет там DLL. Все это MS Specific. И под MS Specific мы имеем создание проекта, который делает либо EXE, ибо DLL, и каждую из них — компилирует и собирает по отдельности, с учетом требований стандарта. Это то, что мы реально имеем. И если то, что мы реально имеем, противоречит стандарту, то надо работать применительно к реальной ситуации, а не упорно требовать исполнения стандарта. Потому что требовать не от кого, а писать программу надо.

E>Ну там well formed programme, ill formed programme... Не встерчал?




E>Кстати, programme без функции main она того, ill formed... Как это, по твоему, вяжется с DLL?


Еще раз — все это MS Specific.

PD>>Есть компилируемая и собираемая единица (EXE, DLL).

E>А как эта "собираемая единица" называется в стандарте? Я давно читал, конечно, лет пять назад, может с тех пор что-то переписали. Но тогда я встречал термин "programme" и термин "translation unit", что ли... А как называется "собираемая единица" я даже и представить не могу. "assembling unit"?

Называй как хочешь или вообще не называй. Коль скоро этого нет в стандарте, то это нестандартное расширение. А поэтому надо адресоваться не к стандарту, а к Microsoft Specific

PD>>Они независимы вообще-то, так что стандарт применяй к каждой из них. И есть нестандартное расширение — экспорт, и в отношении его действуют правила MS, а не стандарта.

E>Да? Правда? И где в DLL функция main? Когда она получает управление? В какой взаимосвязи с этой функцией находятся конструкторы и деструкторы глобальных объектов?

И опять — все это Microsoft Specific. Про деструкторы и конструкторы, полагаю, знаешь сам — когда они вызываются для глобальных DLL объектов.



E>Никак не описано. И DLL и COM и многопоточность -- это расширения стандарта. Он не накладывает на реализацию никаких ограничений по этому поводу. Но реализация сама может накладывать на себя ограничения и давать свои гарантии...


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

E>>>Значит то, что я могу, например, передать экземпляр этого класса из DLL в EXE, или наоборот... МОгу передать указатель и звать методы, могу работать с полями...

PD>>ИМХО это недопустимо.

E>Э-э-э. Я бы ещё понял, "AFAIK", но "IMHO"? При чём тут YHO? Тут, IMHO, намного важнее HO авторов реализации


. Если можно, приведи мнение авторов реализации насчет того. что это допустимо.


E>Я знаю как это сделано на нескольких платформах в нескольких реализациях (SO, Dll, ShLb, оверлеи...)


Можно конкретный пример, где именно и что сделано. У меня нет времени копаться в исходниках неизвестных мне продуктов.

E>И везде такое можно... Не затруднит привести реализацию, в которой нельзя?..


Да в любой нельзя, если нет экспорта. Потому что это внутренняя структура(класс) DLL. При разработке этой DLL я публикую ее интерфейс, то есть то, что она экспортирует. То, что не экспортирует — не публикую, а стало быть, это никому не должно быть известно. Могу там любые классы и типы внутри определить, как мне захочется. А DLL не есть часть EXE. DLL есть совершенно независимый продукт. И разработчик EXE, используя эту DLL, имеет право пользоваться только опубликованной информацией, и не имеет — непубликуемой. Вот и все. А если какие-то системы публикуют все (хотя я и не пойму, как такое вообще возможно, что там экспортируется, локальные типы тоже ? нет, наверное), значит, все так же, только публикация всего по умолчанию.

А впрочем, можно и проще объяснить. Тебе понятие "файлы символов" знакомо ? Микрософт их распространяет для своих системных DLL, их можно использовать для отладки и т.д. Вот они как раз и содержать всю информацию о внутренних (неэкспортируемых) объектах DLL. Устанавливаешь их на своем компьютере, и можешь трассировать код системных функций на уровне имен/типов. У Фень Юаня так win32k.sys исследуется. Это и есть то, что ты предлагаешь. Только вот одно но — это все только для отладки, в каких бы то ни было продуктах эти файлы никогда не используются, да и вряд ли они вообще redistrivutable.


E>Ну это зависит от реализации, конечно, но это так в MSVC и в MWCW. А вот в SO'шках GCC по умолчанию экспортируется вообще всё. Они в этом смысле намного более похожи на .lib'ы...


Так если экспортируется все, значит, я прав. Только экспорт, но неявный. Ты мне пример приведи, где экспорта нет. Никакого. Есть класс в DLL, и никак он не фигурирует нигде, кроме как в ней самой. А доступ есть.

E>

E>Но если вернуться к нашему вопросу, что будет, если я в DLL опишу класс одним образом, а в EXE другим, и передам указатель на экземпляр такого класса из DLL в EXE или обратно, то я хотел бы заметить, что С++ так спроектирован, что классы всё равно идентифицируются именно по имени. И именно для того, чтобы не было накладок и требуется, чтобы соблюдалось ODR. А так, нет проблем его нарушить. Смотри: [c]// shared.h

<skipped>

Ну не надо так. Программа будет корректна даже без всяких DLL, просто в одном EXE вполне можно описать два различных класса с одним и тем же именем, но разной областью видимости. Чай, не в C# мы все же, типы не глобальны А для DLL мы имеем фактически то же самое , только Microsoft Specific способом. Видимость не на уровне вложенности или static, а на уровне модулей.

Егор, ИМХО наши разногласия в том, что ты упорно требуешь от меня доказательств в соответвствии со стандартом, а я тебе упорно объясняю, что это нестандартное расширение/модификация, а поэтому искать в стандарте ответы на это бессмысленно. Если ты с этим не согласен, то зафиксируем разногласия и закончим дискуссию. Если согласен, то не надо больше ссылок на стандарт, а тогда и можно обсудить, почему из DLL нельзя использовать непубликуемые типы. В соответствии с MS Specific
With best regards
Pavel Dvorkin
Re[7]: DLL и <dynamic_cast>
От: byleas  
Дата: 11.09.09 08:48
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>А тогда непонятно, что ты хочешь.

Я уточнил просто.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.