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

Вниз

Вопрос по классам KOL...   Найти похожие ветки 

 
rainstuff   (2006-03-13 02:18) [0]

У меня вот такой вопрос, возможно ламерский:)
Насколько я понял, PCanvas:=^TCanvas;
Тогда почему не работает код:
var
 canv1:PCanvas;
 canv2:TCanvas;
begin
   canv1:=Form.Canvas;
   canv2:=canv1^;
   canv2.TextOut(10,10,"123");
end;

Delphi 5, Kol 2.33, Windows XP
Спасибо.


 
ECM ©   (2006-03-13 09:55) [1]

Потому, что canv2 (как область памяти) оказывается неинициализированной.
Самое главное в ней отсутствует ссылка на VMT, вернее она указывает на произвольную область памяти и при копировании объекта, функция System._ObjCopy не может правильно определить размер объекта (возможно даже прочитать ячейку где хранится размер) - дальше AV.
Для объекта обязательно должна быть вызвана функция Setup._ObjSetup  
компилятор сам добавит её вызов при вызове конструктора


 
ECM ©   (2006-03-13 12:57) [2]


> Setup._ObjSetup

Опечатка System._ObjSetup


 
rainstuff   (2006-03-13 15:48) [3]

Спасибо, за ответ, но я не совсем понял, как вызвать эту функцию....
А можно пример, если не сложно?


 
ECM ©   (2006-03-13 16:41) [4]


> но я не совсем понял, как вызвать эту функцию....

Очень просто
1) _ObjSetup:
  New(canv1,Create());
2)_ObjCopy
 canv2 := canv1^;

Компилятор сам вставит вызовы за вас :))
Либо нужно писать на ассемблере.
А вообще-то я не вижу никакого смысла в использовании статических или автоматических объектных переменных (не-указателей). Компилятор не вызывает для них автоматически конструктор-деструктор, выделение-освобождение памяти, как например для строк. Для классов это уже заложено изначально - только ссылки. Поэтому совет - пользуйтесь только указателями на объектный тип и не заморачивайтесь.

Хотя можно и извратится, например так:

 PInteger(@canv2)^ := Integer(TypeOf(TCanvas));
 canv2 := Form.Canvas^;
 canv2.TextOut(10,10,"123");


 
rainstuff   (2006-03-13 16:50) [5]

Спасибо!
Да я б не заморачивался, но дело в том, что у меня есть dll, написанная на Delphi с использованием VCL.  И туда в функцию надо передать объект для последующей обработки. К примеру, в dll есть такая функция:
function PluginExec(Canvas:TCanvas):Boolean;
Если писать без KOL - передаётся туда   PlugExec(Canvas) и всё работает...
А вот когда стал писать на KOL, то возникли некоторые проблемы...


 
ECM ©   (2006-03-13 17:02) [6]

Вот именно!

function PluginExec(Canvas: TCanvas):Boolean; (VCL TCanvas - class)
Canvas - ссылка (грубо говоря указатель) 4 байта

соответствует в KOL следующему:
function PluginExec(Canvas: PCanvas): Boolean;
т.е. передается в ДЛЛ указатель на объект основной программы - как и вслучае VCL. Если же писать TCanvas в KOL - будет передаваться копия переменной через стэк

:)


 
rainstuff   (2006-03-13 17:27) [7]

Я пробовал... вызывал PluginExec(Form.Canvas),но  почему-то вылетает с RuntimeError...
потому и подумал, что может дело в указателях...


 
ECM ©   (2006-03-13 17:57) [8]

Ну... тут может быть тысяча причин..:)) Надо увидеть как в DLL используется этот указатель. А вообще-то (ИМХО) пользоваться в DLL объектами (классами) основной программы не есть хорошо. Где гарантия, что в основной программе и в DLL используется одна и таже версия - вплоть до двоичного представления (теоритически возможна разница  допустим при одной и той же версии исходного кода но при разных опциях компилятора) и тогда жди AV...Немного легче при использовании стандартных компонент VCL(они не обновляются часто, по крайней мере в пределах одной версии Delphi) - но и там я бы не стал так делать. Если надо что-то нарисовать из DLL в контекст основной программы - передайте DC
(Canvas.Handle)


 
rainstuff   (2006-03-13 18:03) [9]

хм... может так и сделаю...
а вылетает оно как раз после попытки что-нибудь нарисовать, если конкретно:
Canvas.TextOut(X,50,"123");


 
rainstuff   (2006-03-13 18:41) [10]

Не, с дескриптором тоже не получается - в программе работает, а в dll - нет... (специально написал свою dll...)
без KOL всё работает на ура... где собака зарыта я так и не понял...
Ладно, бум копать:)
В любом случае - спасибо за помощь:)


 
rainstuff   (2006-03-13 19:06) [11]

С DC настроил - всё работает, но при передаче Canvas по-прежнему вылетает...


 
Vladimir Kladov   (2006-03-13 20:53) [12]

В DLL и в экзешнике различные менеджеры памяти. Т.е. они может и одинаковые даже, если версии совпадают, но память выделяется в разных областях памяти и структурах кучи. А теперь представьте себе... Представили? И больше никогда не пассируйте объекты между DLL и экзешником. Даже если вдруг заработает. Сохраните себе кучу нервных окончаний.


 
Vladimir Kladov   (2006-03-13 21:12) [13]

Думал, добавить, не добавить. Ну ладно, рискну. Если из головной программы в DLL передать адрес структуры MemoryManager, и в DLL в этом вызове (первом) вызвать SetMemoryManager, то это будет полный аналог uses sharemem в VCL Delphi. т.е. куча становится общая, и проблемы исчезнут. Но все равно, лучше так не делать. KOL не VCL, версии меняются часто. Поля в объектах "плавают", и при несовпадении версии случиться может что угодно, вплоть до синего экрана или форматирования винта (без шуток). Лучше объекты и Huge (Ansi) string не пассировать никогда и ни под каким соусом.


 
ECM ©   (2006-03-13 21:24) [14]

Полностью поддерживаю... думал про то же ... донести правильно не сумел. :(

:))


 
rainstuff   (2006-03-13 23:56) [15]

Мне просто интересно стало- почему не работает:)
Про разные области памяти я знал, но не знал, что это может привести к таким сурьёзным последствиям...



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

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

Наверх




Память: 0.5 MB
Время: 0.046 c
15-1164834016
Cyrax
2006-11-30 00:00
2006.12.24
Структура .vdx-файлов


4-1155821441
apic
2006-08-17 17:30
2006.12.24
Короткий путь


15-1164879601
Fox
2006-11-30 12:40
2006.12.24
Вакансия Технический писатель


15-1164727925
SysError
2006-11-28 18:32
2006.12.24
архив форума


2-1165300164
ПытливыйУМ
2006-12-05 09:29
2006.12.24
Перемищать форму за WebBrowser