![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Вопрос по классам KOL...
rainstuff © (2006-03-13 02:18:00)У меня вот такой вопрос, возможно ламерский:)
Насколько я понял, 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
Спасибо.
rainstuff (2006-03-13 23:56:00) [1]Мне просто интересно стало- почему не работает:)
Про разные области памяти я знал, но не знал, что это может привести к таким сурьёзным последствиям...
ECM (2006-03-13 21:24:00) [2]Полностью поддерживаю... думал про то же ... донести правильно не сумел. :(
:))
Vladimir Kladov (2006-03-13 21:12:00) [3]Думал, добавить, не добавить. Ну ладно, рискну. Если из головной программы в DLL передать адрес структуры MemoryManager, и в DLL в этом вызове (первом) вызвать SetMemoryManager, то это будет полный аналог uses sharemem в VCL Delphi. т.е. куча становится общая, и проблемы исчезнут. Но все равно, лучше так не делать. KOL не VCL, версии меняются часто. Поля в объектах "плавают", и при несовпадении версии случиться может что угодно, вплоть до синего экрана или форматирования винта (без шуток). Лучше объекты и Huge (Ansi) string не пассировать никогда и ни под каким соусом.
Vladimir Kladov (2006-03-13 20:53:00) [4]В DLL и в экзешнике различные менеджеры памяти. Т.е. они может и одинаковые даже, если версии совпадают, но память выделяется в разных областях памяти и структурах кучи. А теперь представьте себе... Представили? И больше никогда не пассируйте объекты между DLL и экзешником. Даже если вдруг заработает. Сохраните себе кучу нервных окончаний.
rainstuff (2006-03-13 19:06:00) [5]С DC настроил - всё работает, но при передаче Canvas по-прежнему вылетает...
rainstuff (2006-03-13 18:41:00) [6]Не, с дескриптором тоже не получается - в программе работает, а в dll - нет... (специально написал свою dll...)
без KOL всё работает на ура... где собака зарыта я так и не понял...
Ладно, бум копать:)
В любом случае - спасибо за помощь:)
rainstuff (2006-03-13 18:03:00) [7]хм... может так и сделаю...
а вылетает оно как раз после попытки что-нибудь нарисовать, если конкретно:
Canvas.TextOut(X,50,'123');
ECM (2006-03-13 17:57:00) [8]Ну... тут может быть тысяча причин..:)) Надо увидеть как в DLL используется этот указатель. А вообще-то (ИМХО) пользоваться в DLL объектами (классами) основной программы не есть хорошо. Где гарантия, что в основной программе и в DLL используется одна и таже версия - вплоть до двоичного представления (теоритически возможна разница допустим при одной и той же версии исходного кода но при разных опциях компилятора) и тогда жди AV...Немного легче при использовании стандартных компонент VCL(они не обновляются часто, по крайней мере в пределах одной версии Delphi) - но и там я бы не стал так делать. Если надо что-то нарисовать из DLL в контекст основной программы - передайте DC
(Canvas.Handle)
rainstuff (2006-03-13 17:27:00) [9]Я пробовал... вызывал PluginExec(Form.Canvas),но почему-то вылетает с RuntimeError...
потому и подумал, что может дело в указателях...
ECM (2006-03-13 17:02:00) [10]Вот именно!
function PluginExec(Canvas: TCanvas):Boolean; (VCL TCanvas - class)
Canvas - ссылка (грубо говоря указатель) 4 байта
соответствует в KOL следующему:
function PluginExec(Canvas: PCanvas): Boolean;
т.е. передается в ДЛЛ указатель на объект основной программы - как и вслучае VCL. Если же писать TCanvas в KOL - будет передаваться копия переменной через стэк
:)
rainstuff (2006-03-13 16:50:00) [11]Спасибо!
Да я б не заморачивался, но дело в том, что у меня есть dll, написанная на Delphi с использованием VCL. И туда в функцию надо передать объект для последующей обработки. К примеру, в dll есть такая функция:
function PluginExec(Canvas:TCanvas):Boolean;
Если писать без KOL - передаётся туда PlugExec(Canvas) и всё работает...
А вот когда стал писать на KOL, то возникли некоторые проблемы...
ECM (2006-03-13 16:41:00) [12]
> но я не совсем понял, как вызвать эту функцию....
Очень просто
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 15:48:00) [13]Спасибо, за ответ, но я не совсем понял, как вызвать эту функцию....
А можно пример, если не сложно?
ECM (2006-03-13 12:57:00) [14]
> Setup._ObjSetup
Опечатка System._ObjSetup
ECM (2006-03-13 09:55:00) [15]Потому, что canv2 (как область памяти) оказывается неинициализированной.
Самое главное в ней отсутствует ссылка на VMT, вернее она указывает на произвольную область памяти и при копировании объекта, функция System._ObjCopy не может правильно определить размер объекта (возможно даже прочитать ячейку где хранится размер) - дальше AV.
Для объекта обязательно должна быть вызвана функция Setup._ObjSetup
компилятор сам добавит её вызов при вызове конструктора