Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Вопрос по классам 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  
компилятор сам добавит её вызов при вызове конструктора


Наверх

Титульная страница Поиск, карта сайта Написать письмо