Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Вниз

передача объектов с DLL   Найти похожие ветки 

 
novichek   (2010-01-08 18:39) [0]

только начинаю осваивать работу с dll

в DLL описал процедуру, которая находится в моём приложении
 SetImage: procedure (bmp: Graphics.TBitMap);

после загрузки DLL передаю адрес этой процедуры.

procedure SetImage(bmp: TBitMap); stdcall;
begin
ShowMessage(IntToStr(bmp.Width)); // acces
end;

в dll создается битмап и вызывается процедура приложения где он и передается параметром.. ну и получаю acces если пытаюсь в этом обработчике обратиться к любому свойству этого битмапа.

всякие там числа, строки нормально передаются...
может как-то по-другому нужно объекты передавать?


 
Palladin ©   (2010-01-08 18:48) [1]

А тебе кто разрешил передавать экземпляры классов Delphi между хост-приложением и dll ?


 
novichek   (2010-01-08 18:49) [2]

я думал не нужно разрешения )

так что получается, никак нельзя?


 
Palladin ©   (2010-01-08 18:57) [3]

Разрешение нужно, но тебе его все равно не дадут )


> так что получается, никак нельзя?

Ну отчего же, запросто можно, например, создать объект системы типа HBITMAP. Передать его в (или принять от) хост приложения и работать с ним сколько душе угодно. Есть другая куча способов передачи данных в независимых от среды разработки форматах, особенно учитывая, что память у dll и хоста общая.


 
Не занят   (2010-01-08 18:57) [4]


> ну и получаю acces


Не может быть. Наоборот, не должен его получать.


 
novichek   (2010-01-08 19:02) [5]

спасибо, попробую копать в сторону HBITMAP
тяжко пока на этом winapi работать..

Не занят,  
   да нет, вылетает ошибка при попыьке обратиться к любому свойству..

"Есть другая куча способов"   не могли бы подсказать где почитать можно про это? по каким параметрам гуглить?


 
Palladin ©   (2010-01-08 19:10) [6]

Вот, к сожалению, погуглить на тему передачи именно битмапов или, тех или иных, объектов Delphi, тут особо не получится, ибо тема не сильно тривиальна. Можно сохранить его в TMemoryStream, передать указатель, а потом оттуда-же считать.

А вообще обмен данными между хостом и dll сводится к обмену указателями на тот или иной выделенный участок памяти и, в случае необходимости конечно, его (участка) размер. Вот это и будет самый независимый от ЯП обмен данными )


 
novichek   (2010-01-08 19:21) [7]

"между хостом и dll сводится к обмену указателями "

попробывал передавать указатель

 type
    bbb = ^TBitMap;

.....

procedure SetImage(bmp: bbb); stdcall;
begin
 ShowMessage( TBitmap(@bmp).Width) );
end;

та же хрень.. или смысл был в другом?

попробывал бегло покопать в сторону HBITMAP - ужас!
как тяжко там создавать и рисовать...


 
Palladin ©   (2010-01-08 19:28) [8]


> novichek   (08.01.10 19:21) [7]

Ну еклмн!!, зри глубже, передача указателей на указатели, а объекты классов делфи именно таковыми и являются, ничем не отличается от передачи самих объектов. Не нужно передавать ни объекты делфи, ни указатели на объекты делфи, ни указатели на указатели на объекты делфи, и т.д.! Какая к хрену разница передал ты объект делфи или указатель на него. От этого он объектом быть не перестанет, а вот RTTI у них будет зело разная!


 
novichek   (2010-01-08 20:27) [9]

не, работу с HBITMAP я не потяну)

посдкажите пожалуйста, если я буду передавать с dll Tbitmap.handle, который HBITMAP,
как в проге с полученного HBITMAP сделать TBitMap дельфей?

что - то вообще гугль по работе с HBITMAP в Delphi не хочет рассказывать :(


 
Anatoly Podgoretsky ©   (2010-01-08 20:45) [10]

> novichek  (08.01.2010 20:27:09)  [9]

У тебя неправильный Гугл.


 
novichek   (2010-01-08 21:07) [11]

да вот час уже сижу читаю..

ну дайте кусочек кода как создать TbitMap имея HBITMAP ?

да, если это конечно поможет мне с передачей картинки от dll к проге.. :)


 
Джо ©   (2010-01-08 21:53) [12]


> ну дайте кусочек кода как создать TbitMap имея HBITMAP ?

Bitmap := TBitmap.Create
Bitmap.Handle := Handle


 
Джо ©   (2010-01-08 21:53) [13]

Честное слово, в справке всё написано :)


 
novichek   (2010-01-08 22:19) [14]

да пробывал, нифига не работает...
вроде бы и параметры создаваемого битмапа такие же делал, а нифига..


 
sniknik ©   (2010-01-08 22:47) [15]

> да пробывал, нифига не работает...
> вроде бы и параметры создаваемого битмапа такие же делал, а нифига..
очень информативно. сейчас кто нибудь скажет где у тебя ошибка, по этой полной информации...
p.s. лично я ставлю на 17ю строку...


 
Jeer ©   (2010-01-08 23:04) [16]

.. x mod 17 :)


 
korneley ©   (2010-01-08 23:18) [17]

Телепатор дымит уже, но подозреваю, что всё ещё, невзирая на рекомендации [6] мыши продолжают жевать свой кактус (TBitmap из dll)


 
novichek   (2010-01-08 23:28) [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;


 
DVM ©   (2010-01-08 23:34) [19]


> novichek

в dll лучше всего передавать указатель на массив, в котором содержатся непосредственно данные битмапа, а также ширину, высоту и цветность. В большинстве случаев так и делют и никаких HBITMAP не надо. А dll уже сама полученные данные интерпретирует.


 
DVM ©   (2010-01-08 23:35) [20]


> var
>  SetImage: procedure (bmp: HBitMap); stdcall;
>
> ....
>    bmp.Width:= 1024;
>    bmp.Height:= 200;

это ерунда написана


 
novichek   (2010-01-08 23:38) [21]

планировал в общем dll создавать в виде плагинов.
там должно формироваться изображение и передаваться проге,
которая будет данный битмап в оверлее выводить на видео.
битмапов около 4-х.
обновления каждого примерно 300 мс.
вот думаю использование данного метода в плагинах ресурсоемко в отличии если всё это делать в самой проге и забить на плагины...
к то му же пол дня впустую ушло с этой передачей..


 
novichek   (2010-01-08 23:41) [22]

DVM, не могли бы вы показать код как разложить дельфей битмап в массив и потом как из массива собрать битмап?

"это ерунда написана"   почему?


 
oxffff ©   (2010-01-08 23:43) [23]

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)


 
DVM ©   (2010-01-08 23:51) [24]


> novichek   (08.01.10 23:41) [22]


> "это ерунда написана"   почему?

HBitmap - это не класс и не запись у него нет полей и методов. Это хендл - целое число. Ты же поменял тип параметра у процедуры и думаешь все будет ОК, несмотря на то, что продолжаешь передавать туда опять же свой Graphics.TBitmap.


 
DVM ©   (2010-01-08 23:53) [25]


> novichek

Вообще говоря, несмотря на то, что у DLL и основной программы разные RTTI и вообще говоря классы TBITMAP внутри DLL и основной программы - это не одно и то же, но если они собраны с помощью одной и той же версии дельфи, то они формально идентичны и даже твоя не совсем верная запись должна работать как уже сказали. Но так делать не следует ибо нет гарантии, что работать будет всегда.


 
oxffff ©   (2010-01-08 23:58) [26]

Вот тебе пример все работает напрямую.

Потребитель

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


 
novichek   (2010-01-09 00:03) [27]

DVM, спасибо большое, начинаю нконец-то понимать..

если разрешите, последний вопрос, на будущее что бы знать..
если я когда ума немного наберусь, что бы реализовать такую схему плагинов, которые должны передавать проге битмапы для оверлея и появится необходимость, что бы имели возможность писать плагины сторонние люди на том же с++ какой алгоритм.методику посоветуете использовать?


 
sniknik ©   (2010-01-09 00:04) [28]

пример
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:05) [29]

oxffff, спасибо огромное!
сейчас переварю..


 
sniknik ©   (2010-01-09 00:06) [30]

> если я когда ума немного наберусь, что бы реализовать такую схему плагинов
если наберешься ума, то откажешься от идеи плагинов... в подавляющем большинстве случаев они лишние/только мешают.


 
novichek   (2010-01-09 00:17) [31]

sniknik, спасибо за пример и совет!

одно меня заставляет смотреть в сторону плагинов - дать возможность другим писать вывод в оверлее как им нравится.. к то му же я сильно в графике не силен, движок вывода я написал, вот простенький плагин сделать, который будет управлять движком и передавать битпамы ему и пока хватит.. кому нужен красивый вывод текста (с тенью там, окантовкой и т.п.) пусть уже плагины под себя и пишут.

спасибо вообщем ребята за всё!


 
DVM ©   (2010-01-09 00:19) [32]


> что бы имели возможность писать плагины сторонние люди на
> том же с++ какой алгоритм.методику посоветуете использовать?
>

Для этого надо отказаться от всего, что специфично для Delphi и отсутствует в других языках. Идеально передавать в DLL указатели на области памяти, где что-то лежит или куда что-то нужно положить и указывать при этом размеры области.
В случае с изображениями, как я уже говорил в длл можно передавать битовую карту изображения - указатель на массив "пикселов" а также ширину, высоту и цветность картинки. Плюс соглашение о вызовах надо использовать подходящее. Луче всего stdcall как в WinAPI. Вообще смотри как объявляются функции в WinAPI - они спроектированы для вызовов из программ написанных на разных языках программирпования.


 
sniknik ©   (2010-01-09 00:41) [33]

> пусть уже плагины под себя и пишут.
т.е. ты хочешь свалить то что сам считаешь более сложным на кого то другого? а подумай, если этот другой сможет это, то неужели он не справится и с твоей частью (да еще и получше тебя, т.к. ты "в графике не силен" потому и движок полноценный под нее вряд ли сделаешь)? насколько вообще та часть, что ты оставляешь  себе сложна и востребована? т.е. будет ли стоить свеч написание плагина (+ изучение твоей логики), если будет проще написание всей программы целиком? или, пусть даже прога будет востребована, но с "кривым" интерфейсом, который ты предлагаешь менять в плагинах, думаешь это будет зачтено как + программе? кто вообще захочет взяться за доведение твоей проги "до ума", т.е. помогать тебе развивать прогу, писать под нее "затычки", ради чего?
в общем коротко. нафига это кому то будет нужно, писать тебе плагины?


 
Bunsha   (2010-02-27 00:10) [34]

Я вот тоже недавно столкнулся с проблемой написания плагинов. Была работка написать систему сбора данных, при этом состав оборудования и мат-обработка на момент постановки задачи полностью определены не были.

Что я только не перепробовал.. и dll и пакеты, com-обьекты.

При работе с dll надо помнить, что там где память выделяете, там и надо освобождать, т.к. менеджеры памяти у них разные. Использование ShareMem частично решает этот вопрос. Кстати в справке ошибочно написано, что он нужен только для работы с AnsiString. На самом деле он нужен при работе с любыми динамическими структурами (объекты, массивы).
Плюс проблема с RTTI остается. Поэтому данные в большинстве случаев приходится принудительно приводить к нужному типу (а то потом чудеся появляются типа "не могу присвоить TFont к TFont" :) ).

Это все можно убрать использованием пакетов, но там свои оччень непонятные проблемы.

Самое красивое - COM - обьекты. Но оверхед....

Я лично остановился на Interface. проблем с RTTI нет (они однозначно по GUID идентифицируются), плюс менеджмент памяти всегда выполнятся в контексте самого интерфейса. Оверхед на двойное разименовывание, как и у динамических методов. Плюс бонус - автоматический подсчет ссылок.


 
icWasya ©   (2010-02-27 10:53) [35]

Как работать с 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;



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

Форум: "Начинающим";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.55 MB
Время: 0.09 c
15-1266355805
Юрий
2010-02-17 00:30
2010.08.27
С днем рождения ! 17 февраля 2010 среда


6-1217411834
Lamer666
2008-07-30 13:57
2010.08.27
Сессии HTTPS


2-1274084890
REX
2010-05-17 12:28
2010.08.27
метод ExecSQL (компонент ADOQuery)


2-1270206011
Константин
2010-04-02 15:00
2010.08.27
Как правильн вызвать Destroy?


2-1271155086
JohnKorsh
2010-04-13 14:38
2010.08.27
Как программно нажать кнопку?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский