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

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

передача TStream из DLL


Страницы:   1 2

fford ©   (2010-03-09 13:32:00) 

Здравствуйте!
Вот нашел в инете такую статью
http://www.delphilab.ru/content/view/244/1/
решил попробовать передачу потока из DLL в программу.
Собственно
сделал DLL, где есть функция которая собирает все фалы из указанного каталога в один, формирует поток и передает его тому кто вызвал :)

function GetText(Path,FileName:Pchar):IStream; stdcall;
Var m:TMemoryStream;
   st:TStrings;
Begin
m:=TMEmoryStream.Create;
st:=ReadFilesTo(StrPas(Path),StrPas(FileName));  //функция собственно собирает файлики и делает из них один, возвращая TStrings
st.SaveToStream(m);
result:=TStreamAdapter.Create(m, soOwned) as IStream;
st.Free;
End;


в программе описал следующую процедуру:

Procedure ExGetText(Path,FileName:String):TStrings;
Var lib:THandle;
   f:Function(Path,FileName:PChar):IStream; stdcall;
   mem:TStringList;
   tmp:TExternStream;
Begin
lib:=LoadLibrary('c:\primer.dll');
if lib<>0 Then
 Begin
  @f:=GetProcAddress(lib,'GetText');
  if @f<>nil Then
   Begin
    tmp:=TExternStream.Create(f(PChar(Path),PChar(FileName)));
    mem:=TStringList.Create;
    tmp.Position:=0;
    mem.LoadFromStream(tmp);
    mem.SaveToFile('c:\1.ttt');
    tmp.Free;
   end;
  FreeLibrary(lib);
 End;
End;


здесь класс TExternStream взят из статьи по ссылке описанной выше.
сделал каталог на диске покидал туда пару текстовиков
запустил процедуру на выполнение. Все прекрасно
на диске C: создался файл 1.ttt который содержит собственно конкатенацию файлов. т.е. все замечательно все работает
кроме одного

в строке FreeLibrary(lib);
программа вылетает с Access violation по такому-то адресу  
немогу понять почему :(
я предполагаю что, когда я пытаюсь освободить память занятую этой DLL
кусок её, через IStream связан с основной программой (грубо)
но вроде бы по описанию
soOwned The stream is owned by the object that uses it (and exists solely for that object). The object that uses the stream frees the associated stream when it no longer needs to use the stream.

т.е. tmp.Free; должен освобождать поток, который создала DLL

где грабли? :)


fford   (2010-03-09 14:25:00) [21]

блин ничего не понимаю
по идее
работает так
1. создали поток в памяти DLL
2. создали интерфейс и связали его с потоком
3. программа получила данные из этого потока через переданный интерфейс
4. программа обнулила ссылку на интерфейс, т.е. его более никто не использует и он может спокойно быть разрушен
5. программа выгружает DLL освобождая память выделенную ей.

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

и как же тогда все по честному освободить ? ведь если я вызову много раз в программе буду вызывать эту длл с её функцией, то память будет утекать ...
или винда сама будет выгружать эту DLL при неиспользовании никем интерфейса ?


fford   (2010-03-09 14:11:00) [22]


> зачем же интерфейсной ссылке делать фри?

а ей вроде никто и не делает фри
освобождается объект класса TExternStream
а его деструкторе интерфейсную ссылку обнуляют
что собственно и приводит к освобождению
т.к. на этот интерфейс уже нет ни одной ссылки


Медвежонок Пятачок   (2010-03-09 14:02:00) [23]

зачем же интерфейсной ссылке делать фри?


fford   (2010-03-09 13:54:00) [24]

причем все равно
делаю я  tmp.free
или его комментирую

Access violation всеравно  вылетает :(


fford   (2010-03-09 13:52:00) [25]

как я написал я взял класс из статьи

и освобождаю так же как и у автора в примере:
var
 aOut : TExternStream;
try
 aOut := TExternStream.Create(strm);
 Image1.Picture.Bitmap.LoadFromStream(aOut);
....
 aOut.Free; //Тут уничтожиться поток созданный в Dll, так как указатель на aStream занулиться.


вот мой код
tmp:=TExternStream.Create(f(PChar(Path),PChar(FileName)));
   mem:=TStringList.Create;
   tmp.Position:=0;
   mem.LoadFromStream(tmp);
   mem.SaveToFile('c:\1.ttt');
   tmp.Free;


f(PChar(Path),PChar(FileName)) возвращает IStream
из него копируется в mem
и tmp освбождается


sniknik   (2010-03-09 13:42:00) [26]

> где грабли? :)
в твоей интерпретации/реализации TExternStream, т.к.  в статье все освобождается.


Страницы:   1 2

Наверх

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