Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Приведение типов объектов в DLL


Автор: 790 30.5.2006, 23:58
Всем ку!
Появилась неожиданная проблема.
Есть куча классов, наследуемых от TBaseClass
например: 
TRaspred = class(TBaseClass)
В приложении создаются экземпляры этих классов, заполняются данными, все дела. 
Потом передаются ф-ии из Dll:
Код

fnDAMain(ptrPS:PPS)
,
где 
Код

PPS = ^TPS 
(TPS тож наследуется от TBaseClass)
в DLL в fnDAMain есть такой код:

Код

iIkCnt: integer;
ptrPS: PPS; 
ptrRU: PBASECLASS; //PBASECLASS = ^TBaseClass
...
ptrRU := ptrPS^.GetListObject(i);

{возвращает PBASECLASS. Но по факту указывает на объект класса TRaspred,
и потом}

Код

iIkCnt := (ptrRU^ as TRaspred).GetListCount(2);

На этой строке появляется имсключение EInvalidCast с матом: Invalid type cast.
Хотя! Если эту fnDAMain(ptrPS:PPS) вызывать не через DLL, а просто скомпилить в приложение, то все пучком. 
Смотрел адреса, куда указатели показывают. В приложении и DLL они совпадают.
DLL подключал и явно и неявно. По-барабану. Та же ошибка.
Что это может быть и как это исправить или обойти? 

Автор: Romikgy 31.5.2006, 08:42
Код

    
iIkCnt := TRaspred(ptrRU^).GetListCount(2);

А так если? 

Автор: Snowy 31.5.2006, 09:40
Ты хочешь передавать объекты в dll?
А где описан TBaseClass? И как ты создаешь наследника от него в dll?
Не, так не пойдет. Если dll - юзай интерфейсы.
А лучше юзай bpl. Там всё необходимое уже предусмотрено. 

Автор: 790 31.5.2006, 20:44
Цитата(Snowy @  31.5.2006,  09:40 Найти цитируемый пост)
Ты хочешь передавать объекты в dll?
А где описан TBaseClass? И как ты создаешь наследника от него в dll?

Не объект, а указатель на него. И в DLL работаю с указателями. TBaseClass описан в юните, кот-ый подключается как при компиляции приложения, так и при сборке dll.
Наследник от него создается как
Код

ptrRU: PBASECLASS;
...
{потом надо присвоит этому указателю ссылку на объект (кот-ый на самом деле типа TRaspred, просто ф-ия класс TPS возвращает ука-ль на баз. класс}
ptrRU := ptrPS^.GetListObject(i);
{и получить одно из полей этого объекта класса TRaspred, приведя указ-ль ptrPS к этому типу. Напомню, что TRaspred = class(TBaseClass)}
iIkCnt := (ptrRU^ as TRaspred).GetListCount(2);
//мат: Invalid type cast. И только в dll


Пользовать интерфейсы и bpl нельзя, т.к. то приложение, кот-ое должно хорошо работать с этой dll, делелось моим начальником неск. месяцев и сдавать проект уже скоро. Если я ему предложу bpl и интерфейсы, он мне ничего хорошего не предложит в ответ  smile . Если серьезно, то уже нет времени разбираться в bpl и интерфейсах.
Мне недавно подсказали, что стоит использовать какое-то ShareMem.
Есть ли еще идеи, что делать?
 

Автор: Snowy 1.6.2006, 08:57
Не получится так.
TBaseClass в exe и TBaseClass в dll, в откомпиленом варианте это совсем разные классы.
Ни о каком приведении и речи быть не может.
Никакой шаремем тут не поможет.
Либо интерфейсы, либо bpl. 
bpl не мешает использовать dll. По сути bpl - это dll с расширенными возможностями. 

Автор: 790 1.6.2006, 22:43
Цитата(Snowy @  1.6.2006,  08:57 Найти цитируемый пост)
TBaseClass в exe и TBaseClass в dll, в откомпиленом варианте это совсем разные классы.
Ни о каком приведении и речи быть не может.

Опа. Вот этого я и не подозревал. Спасибо за науку. Так значит bpl. Хорошо, поковаряюсь с этим.

Кстати, а как бы вы решили эту проблему по сути? Т.е. надо, чтоб dll, подключенная приложением работала с объектами (деревом объектов), созданными в приложении
 

Автор: 790 1.6.2006, 23:05
или не dll, но что-то динамически подключаемое 

Автор: Snowy 2.6.2006, 09:21
Если подключаемый модуль один, то я бы описание класса дал в нем.
Создание и заполнение в exe, использование в модуле.

Если модулей несколько, то создаем третью bpl, в которой описываем класс.
ехе и все подключаемые подключают этот третий модуль и используют класс.

Это все для BPL.

Если мы хотим остаться на dll, то тут другой принцип.
Объекты мы не используем. Но! Мы можем передавать данные.
Оптимально здесь подойдет сериализация.
У тебя есть одинаково описанный клас в ехе и dll. Онинаковые проперти. Все одинаково по именам.
Различаются они своим физическим местонахождением.
Значит создаем наш объект. Сериализуем его в TMemoryStream. Загоняем данные в буфер. Передаём буфер dll-ке. Уничтожаем объект.
В dll: Загоняем буфер в TMemoryStream. Создаём объект. Десериализуем объект из стрима. Используем.
Если твоё дерево наследуется от TConponent, то в нем уже зашита сериализация (SaveToStream).
Если нет, то читай http://forum.vingrad.ru/index.php?showtopic=94245. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)