![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
передача объектов с DLL
novichek © (2010-01-08 18:39:00)только начинаю осваивать работу с dll
в DLL описал процедуру, которая находится в моём приложении
SetImage: procedure (bmp: Graphics.TBitMap);
после загрузки DLL передаю адрес этой процедуры.
procedure SetImage(bmp: TBitMap); stdcall;
begin
ShowMessage(IntToStr(bmp.Width)); // acces
end;
в dll создается битмап и вызывается процедура приложения где он и передается параметром.. ну и получаю acces если пытаюсь в этом обработчике обратиться к любому свойству этого битмапа.
всякие там числа, строки нормально передаются...
может как-то по-другому нужно объекты передавать?
icWasya (2010-02-27 10:53:00) [1]Как работать с Handle, не особенно заморачиваясь с Win API
в программе
var
BMP:TBitmap;
BMP:=TBitmap.Create;
...
DLLProcedure(BMP.Handle);
...
//////////////////////
в DLL
procedure DLLProcedure(BMP_Handle:Graphics.HBITMAP);
var
BMP:TBitmap;
begin
BMP:=TBitmap.Create;
BMP.Handle := BMP_Handle; /* теперь на Handle есть две ссылки - в DLL и в основной программе */
BMP.LoadFromFile(...);
// еще что-то делаем
BMP.ReleaseHandle; /* освободим */
BMP.Free;
end;
Bunsha (2010-02-27 00:10:00) [2]Я вот тоже недавно столкнулся с проблемой написания плагинов. Была работка написать систему сбора данных, при этом состав оборудования и мат-обработка на момент постановки задачи полностью определены не были.
Что я только не перепробовал.. и dll и пакеты, com-обьекты.
При работе с dll надо помнить, что там где память выделяете, там и надо освобождать, т.к. менеджеры памяти у них разные. Использование ShareMem частично решает этот вопрос. Кстати в справке ошибочно написано, что он нужен только для работы с AnsiString. На самом деле он нужен при работе с любыми динамическими структурами (объекты, массивы).
Плюс проблема с RTTI остается. Поэтому данные в большинстве случаев приходится принудительно приводить к нужному типу (а то потом чудеся появляются типа "не могу присвоить TFont к TFont" :) ).
Это все можно убрать использованием пакетов, но там свои оччень непонятные проблемы.
Самое красивое - COM - обьекты. Но оверхед....
Я лично остановился на Interface. проблем с RTTI нет (они однозначно по GUID идентифицируются), плюс менеджмент памяти всегда выполнятся в контексте самого интерфейса. Оверхед на двойное разименовывание, как и у динамических методов. Плюс бонус - автоматический подсчет ссылок.
sniknik (2010-01-09 00:41:00) [3]> пусть уже плагины под себя и пишут.
т.е. ты хочешь свалить то что сам считаешь более сложным на кого то другого? а подумай, если этот другой сможет это, то неужели он не справится и с твоей частью (да еще и получше тебя, т.к. ты "в графике не силен" потому и движок полноценный под нее вряд ли сделаешь)? насколько вообще та часть, что ты оставляешь себе сложна и востребована? т.е. будет ли стоить свеч написание плагина (+ изучение твоей логики), если будет проще написание всей программы целиком? или, пусть даже прога будет востребована, но с "кривым" интерфейсом, который ты предлагаешь менять в плагинах, думаешь это будет зачтено как + программе? кто вообще захочет взяться за доведение твоей проги "до ума", т.е. помогать тебе развивать прогу, писать под нее "затычки", ради чего?
в общем коротко. нафига это кому то будет нужно, писать тебе плагины?
DVM (2010-01-09 00:19:00) [4]
> что бы имели возможность писать плагины сторонние люди на
> том же с++ какой алгоритм.методику посоветуете использовать?
>
Для этого надо отказаться от всего, что специфично для Delphi и отсутствует в других языках. Идеально передавать в DLL указатели на области памяти, где что-то лежит или куда что-то нужно положить и указывать при этом размеры области.
В случае с изображениями, как я уже говорил в длл можно передавать битовую карту изображения - указатель на массив "пикселов" а также ширину, высоту и цветность картинки. Плюс соглашение о вызовах надо использовать подходящее. Луче всего stdcall как в WinAPI. Вообще смотри как объявляются функции в WinAPI - они спроектированы для вызовов из программ написанных на разных языках программирпования.
novichek (2010-01-09 00:17:00) [5]sniknik, спасибо за пример и совет!
одно меня заставляет смотреть в сторону плагинов - дать возможность другим писать вывод в оверлее как им нравится.. к то му же я сильно в графике не силен, движок вывода я написал, вот простенький плагин сделать, который будет управлять движком и передавать битпамы ему и пока хватит.. кому нужен красивый вывод текста (с тенью там, окантовкой и т.п.) пусть уже плагины под себя и пишут.
спасибо вообщем ребята за всё!
sniknik (2010-01-09 00:06:00) [6]> если я когда ума немного наберусь, что бы реализовать такую схему плагинов
если наберешься ума, то откажешься от идеи плагинов... в подавляющем большинстве случаев они лишние/только мешают.
novichek (2010-01-09 00:05:00) [7]oxffff, спасибо огромное!
сейчас переварю..
sniknik (2010-01-09 00:04:00) [8]пример
procedure TForm1.Button1Click(Sender: TObject);
{1}
var
Bmp: HBitMap;
DC: HDC;
begin
Bmp:= CreateBitmap(105, 105, 1, 1, nil);
DC:= CreateCompatibleDC(0);
Bmp:= SelectObject(DC, Bmp);
FillRect(DC, Rect(50, 50, 55, 55), GetStockObject(WHITE_BRUSH));
Bmp:= SelectObject(DC, Bmp);
DeleteDC(DC);
{2}
Image1.Picture.Bitmap.Handle:= Bmp;
//DeleteObject(Bmp);
end;
первую часть делаеш в dll, передаешь Bmp, и в программе присваиваешь (2 часть), должно работать.
novichek (2010-01-09 00:03:00) [9]DVM, спасибо большое, начинаю нконец-то понимать..
если разрешите, последний вопрос, на будущее что бы знать..
если я когда ума немного наберусь, что бы реализовать такую схему плагинов, которые должны передавать проге битмапы для оверлея и появится необходимость, что бы имели возможность писать плагины сторонние люди на том же с++ какой алгоритм.методику посоветуете использовать?
oxffff (2010-01-08 23:58:00) [10]Вот тебе пример все работает напрямую.
Потребитель
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
...
var
Form1: TForm1;
implementation
{$R *.dfm}
function GetMystuff:Tbitmap;stdcall;external 'project2.dll';
procedure DllFreeObject(Obj:Tobject);stdcall;external 'project2.dll';
procedure TForm1.Button1Click(Sender: TObject);
var stuff:TBitmap;
begin
stuff:=GetMystuff;
Self.Canvas.Draw(0,0,stuff);
DllFreeObject(stuff);
end;
Поставщик DLL
library Project2;
{ Important note about DLL memory management: ShareMem must be the
first unit in your library's USES clause AND your project's (select
Project-View Source) USES clause if your DLL exports any procedures or
functions that pass strings as parameters or function results. This
applies to all strings passed to and from your DLL--even those that
are nested in records and classes. ShareMem is the interface unit to
the BORLNDMM.DLL shared memory manager, which must be deployed along
with your DLL. To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters. }
uses
SysUtils,
Graphics,
Classes;
{$R *.res}
var DllBitmap:Tbitmap=nil;
function GetMystuff:Tbitmap;stdcall;
begin
if not assigned(DllBitmap) then
begin
DllBitmap:=TBitmap.Create;
DllBitmap.LoadFromFile('c:\stuff.bmp');
end;
result:=DllBitmap;
end;
procedure DllFreeObject(Obj:Tobject);stdcall;
begin
Obj.free;
end;
exports GetMystuff,DllFreeObject;
begin
DVM (2010-01-08 23:53:00) [11]
> novichek
Вообще говоря, несмотря на то, что у DLL и основной программы разные RTTI и вообще говоря классы TBITMAP внутри DLL и основной программы - это не одно и то же, но если они собраны с помощью одной и той же версии дельфи, то они формально идентичны и даже твоя не совсем верная запись должна работать как уже сказали. Но так делать не следует ибо нет гарантии, что работать будет всегда.
DVM (2010-01-08 23:51:00) [12]
> novichek (08.01.10 23:41) [22]
> "это ерунда написана" почему?
HBitmap - это не класс и не запись у него нет полей и методов. Это хендл - целое число. Ты же поменял тип параметра у процедуры и думаешь все будет ОК, несмотря на то, что продолжаешь передавать туда опять же свой Graphics.TBitmap.
oxffff (2010-01-08 23:43:00) [13]novichek (08.01.10 18:39)
> в dll создается битмап и вызывается процедура приложения
> где он и передается параметром.. ну и получаю acces если
> пытаюсь в этом обработчике обратиться к любому свойству
> этого битмапа .
Если ты все правильно делаешь( у тебя есть экземпляр объекта ), то проблем быть не должно.
То скорее всего у тебя проблемы с тем, что
1. Либо соглашение о вызовах не идентичное
2. Либо разные типы Tbitmap. Поскольку есть путаница
В модуле windows
tagBITMAP = packed record
bmType: Longint;
bmWidth: Longint;
bmHeight: Longint;
bmWidthBytes: Longint;
bmPlanes: Word;
bmBitsPixel: Word;
bmBits: Pointer;
end;
TBitmap = tagBITMAP;
В модуле graphics
TBitmap = class(TGraphic)
novichek (2010-01-08 23:41:00) [14]DVM, не могли бы вы показать код как разложить дельфей битмап в массив и потом как из массива собрать битмап?
"это ерунда написана" почему?
novichek (2010-01-08 23:38:00) [15]планировал в общем dll создавать в виде плагинов.
там должно формироваться изображение и передаваться проге,
которая будет данный битмап в оверлее выводить на видео.
битмапов около 4-х.
обновления каждого примерно 300 мс.
вот думаю использование данного метода в плагинах ресурсоемко в отличии если всё это делать в самой проге и забить на плагины...
к то му же пол дня впустую ушло с этой передачей..
DVM (2010-01-08 23:35:00) [16]
> var
> SetImage: procedure (bmp: HBitMap); stdcall;
>
> ....
> bmp.Width:= 1024;
> bmp.Height:= 200;
это ерунда написана
DVM (2010-01-08 23:34:00) [17]
> novichek
в dll лучше всего передавать указатель на массив, в котором содержатся непосредственно данные битмапа, а также ширину, высоту и цветность. В большинстве случаев так и делют и никаких HBITMAP не надо. А dll уже сама полученные данные интерпретирует.
novichek (2010-01-08 23:28:00) [18]в dll
var
SetImage: procedure (bmp: HBitMap); stdcall;
....
bmp.Width:= 1024;
bmp.Height:= 200;
bmp.Canvas.TextOut(0,0,dateToStr(date));
SetImage(bmp.Handle);
в проге:
procedure SetImage(bmp: HBitMap); stdcall;
var
b: TBitmap;
begin
b:= TBitMap.Create;
b.Width:= 1024;
b.Height:= 200;
b.PixelFormat:= pf24bit;
b.Handle:= bmp;
ShowMessage(IntToStr(b.Width)); // дает 0
b.Free;
end;
korneley (2010-01-08 23:18:00) [19]Телепатор дымит уже, но подозреваю, что всё ещё, невзирая на рекомендации [6] мыши продолжают жевать свой кактус (TBitmap из dll)
Jeer (2010-01-08 23:04:00) [20].. x mod 17 :)