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

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

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


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

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


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

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