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

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

передача массива из DLL [D7]


Страницы:   1 2

GanibalLector ©   (2005-12-04 17:33:00) 

Имеем такой вот массив:

type
  TBasic=packed record
    ID    : Word;        
    Group : Byte;      
    Code  : DWord;      
    Price : DWord;          
    Valid : DWord;      
    Line : String[24];  
end;
PBasicPLU = ^TBasicPLU;
TBasicPLU = array of TBasic;


идея такова.В своем приложении я вызываю библиотеку,которая заполняет данный массив до некоторого размера. В основном приложении я хотел бы получить его длину и,соответственно,все данные.
Но вот не получается с кодом :(

Чтобы было более понятно,я покажу "это" на примере (только не с массивом,а с Integer):

procedure Test(var HMem:Integer);
var
    Value:Integer;
    P:Pointer;
begin
 Value:=3107;
 HMem:=GlobalAlloc(GMEM_DDESHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,SizeOf(Value)+1);
 if HMem>0 then
 begin
   P:=GlobalLock(HMem);
   if Assigned(P) then System.Move(Value,P^,SizeOf(Value));
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var H:Integer;
    P:Pointer;
begin
Test(H);
if H>0 then
begin
  P:=GlobalLock(H);
  Caption:=IntToStr(PInteger(P)^);
  GlobalUnlock(H);
  GlobalFree(H);
end;
end;


Заранее большое спасибо!!!


Anatoly Podgoretsky   (2005-12-09 00:04:00) [1]

И их тоже два варианта
open array parameters
array of type
и
Variant open array parameters
array of const


Alexander Panov   (2005-12-08 23:08:00) [2]

Cash ©   (08.12.05 22:00) [30]
Открытый масив применимо к объявлению


Нет такого понятия - "открытый массив".
Есть 2 понятия - "динамический массив" и "открытый массив параметров".


jack128   (2005-12-08 23:06:00) [3]

Вот, наваял спецом для тебя примерчик как писать в "блок памяти API функций"
procedure TForm1.Button1Click(Sender: TObject);
const
 s: string = 'Мама мыла раму';
 MemCount = {Length(s)} 14 + 1;
var
 SaveMem, P: PChar;
 OldProtect1, OldProtect2: DWORD;
 Temp: DWORD;
begin
 P := @RemoveMenu; // На функциях kernel32 не решился не тестить.  Хоть PAGE_WRITECOPY, но бережённого бог бережет :-)
 Win32Check(VirtualProtect(P,  MemCount, PAGE_WRITECOPY, OldProtect1));
 SaveMem := AllocMem(MemCount);
 try
   Move(P^, SaveMem^, MemCount); // Сохраняем код функции
   Move(s[1], P^, MemCount); // копируем бред.
   Win32Check(VirtualProtect(P, MemCount, OldProtect1, OldProtect2)); // Восстанавливаем старую защиту
   try
     RemoveMenu(0, 0, 0); // пытаемся выполнить функцию
   except
     on E: Exception do
       // AV. Или привелигированная инструкция. Или еще какой бред полез. Правда странно? ;)
       Application.ShowException(E);
   end;
   Win32Check(VirtualProtect(P,  MemCount, PAGE_WRITECOPY, OldProtect1)); // опять получаем права на запись
   Move(SaveMem^, P^, MemCount);    // Восстанавливаем код функции
   Win32Check(VirtualProtect(P, MemCount, OldProtect1, OldProtect2));
 finally
   FreeMem(SaveMem);
 end;
end;


jack128   (2005-12-08 22:47:00) [4]

Cash ©   (08.12.05 22:00) [30]
Открытый масив применимо к объявлению "array of .....".

применимо. Но не в контексте объявления типа.  Еще раз советую обратить внимание на хелп.  Помогает.
Cash ©   (08.12.05 22:00) [30]
Читаем то, что дядя Борланд там написал в коментариях.

ничего не вижу про раздельньные ВАП для dll и exe её использующую.

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

Cash ©   (08.12.05 22:00) [30]
API Windows
тоже имеют свое адресное пространство

:-)  Ясно.  Купи Рихтера и почитай, что такое виртуальное адресное пространство.


Cash   (2005-12-08 22:00:00) [5]

По книжкам учились,? юноша!

Этот термин имеет прямое отношение к данному типу.
Мы не в Паскале, а в Делфи!
Открытый масив записей!
Открытый масив применимо к объявлению "array of .....".
Хотя нет такого типа(......)! Дык по этому и говорят просто "открытый масив"
с динамическим распределением памяти. Суть дела не меняется!
Чел. взял да и сделал двойной указатель, потом при помощи
вызова GetMem выделил под вторичный указатель памяти до][...на.
Ну, так нельзя! Дельфя то ругаться не будет, но и работоспособности это
не прибавит!

... Для dll и EXE память всегда неразделяемая ...
Еще раз прочитай первую строчку поста, и улыбнись.

Нифчего подобного! Для подтверждения моих слов делаем такую вещь:
Открываем Делфи.
Выбираем "Создать-Мастер DLL".
Смотрим и внимательно, со словарем(если без словаря не получается),
Читаем то, что дядя Борланд там написал в коментариях.

А это так, от меня, воспоминания.
При загрузке программы для нее создается страница адресного
пространства требуемого размера. Далее, если программа использует
внешние исполняемые библиотеки, то их код загружается однократно.
Впринципе, как код и самой программы. Далее создаются страницы
адресного пространства для исполняемых библиотек. API Windows
тоже имеют свое адресное пространство, и загружаются в ОП
однократно, далее используются только из ОП.

А как можно разделить, где мое пространство, а где моей DLL-ки?
Только с помощью менеджера памяти! Иначе Программа просто
не сможет оперировать адресами из области DLL!!!

Коллега, вы хотите сказать, что мы без проблем можем пробиться в блоки
памяти API функций. Бред!


jack128   (2005-12-08 15:56:00) [6]

Cash ©   (08.12.05 14:28) [28]
Заметил ;)
Cash ©   (06.12.05 21:17) [14]
Код TBasicPLU = array of TBasic, создаст
открытыймасив

Не верно. Термин _открытый_ массив имеет в дельфи самостоятельное значение, не имееющее к TBasicPLU никакого отнашения.  TBasicPLU - это _динамический_ массив. Очень многие не понимают разницу между этими понятиями. подробности в open arrays + f1

Cash ©   (06.12.05 21:17) [14]
она(память) станет нераздельная для длл-ки
и для проги
 Для dll и EXE память всегда неразделяемая(если я прально понял, что вкладыаваешь в это слово), поскольку они выполняются в едином ВАП. ShareMem всего лишь добавляет общий менеджер памяти в программу.


Cash   (2005-12-08 14:28:00) [7]

Анекдот:
"Пациент:
  Доктор, доктор, помогите..., меня никто... не замечает!
Доктор:
  .... Следующий!"
:)))

Look to (06.12.05 21:17) [14]


jack128   (2005-12-07 21:49:00) [8]

GanibalLector ©   (07.12.05 21:18) [26]
Ну,наконец-то и я получил AV

Поздравляю :-)


GanibalLector   (2005-12-07 21:18:00) [9]

2 jack128 ©
Ну,наконец-то и я получил AV.Правда на другом компьютере(мой до сих пор ее не видит). Проблему разрешил заменив TBasicPLU = array of TBasic;на   TBasicPLU = array[1..10000] of TBasic;и полной заменой кода. :(

>Советую в казино сходить, с таким везением имеешь все шансы Джек Пот сорвать.

А это идея ;)


jack128   (2005-12-07 10:15:00) [10]

Вот у меня av'ка в твоем коде вылазит постоянно..  Ну из 10 экспеременов раз 9 AV и один раз нормально завершится программа.


jack128   (2005-12-07 10:14:00) [11]

GanibalLector ©   (07.12.05 2:06) [19]
О чем речь???

О дин массивах.

GanibalLector ©   (07.12.05 2:06) [19]
Да хоть 100. Нет его!!!

Советую в казино сходить, с таким везением имеешь все шансы Джек Пот сорвать.


Fay   (2005-12-07 07:42:00) [12]

2 Slym ©   (07.12.05 7:37) [22]
> а так - TObject(pointer(1)).Free;
Нет, спасибо 8)


Slym   (2005-12-07 07:37:00) [13]

Fay ©   (07.12.05 7:30) [21]
Просто в образовательных целях

Не цепляйся к букве- тут принцип работы...
а так - TObject(pointer(1)).Free;


Fay   (2005-12-07 07:30:00) [14]

2 Slym ©   (07.12.05 6:24) [20]
> AV тебе в помощь TObject(pointer(0)).Free;
Выполни у себя TObject(pointer(0)).Free.
Просто в образовательных целях.


Slym   (2005-12-07 06:24:00) [15]

GanibalLector ©   (07.12.05 2:06) [19]
Счастливое стечение обстоятельств!
AV тебе в помощь TObject(pointer(0)).Free;


GanibalLector   (2005-12-07 02:06:00) [16]

2 jack128 ©   (07.12.05 00:38) [18]
>Да? Я тебе такого не советовал..
О чем речь???

>Нажми на кнопку раз 20-30 подряд, а потом закрой приложение - 100% выскочит.
Да хоть 100. Нет его!!!


jack128   (2005-12-07 00:38:00) [17]

Да? Я тебе такого не советовал..

ps не нужели у тебя ни разу ав'шки не выскочило при тестировании этого кода??  Нажми на кнопку раз 20-30 подряд, а потом закрой приложение - 100% выскочит.
jack128 ©   (05.12.05 12:32) [8]
ClobalUnlock( H);
//сорри


GanibalLector   (2005-12-06 23:53:00) [18]

2 jack128 ©  
Мой окончательный вариант(с твоими доработками...за что тебе отдельное спасибо). Ни мемликов,ни утечек нет.

type
 TBasic=packed record
   Id:Byte;
   Line : String[24];
 end;
 PBasicPLU = ^TBasicPLU;
 TBasicPLU = array of TBasic;

procedure Test(var HMem:Integer);
var Value:TBasicPLU;
   P:Pointer;
   I:Integer;
begin
SetLength(Value,random(100)+1);
for I:=0 to Length(Value)-1 do
begin
  Value[I].Id:=I;
  Value[I].Line:='Test'+IntToStr(I);
end;
HMem:=GlobalAlloc(GMEM_DDESHARE or GMEM_MOVEABLE or GMEM_ZEROINIT,
       SizeOf(TBasic)*Length(Value)+SizeOf(Integer)+1);
if HMem>0 then
begin
  P:=GlobalLock(HMem);
  if Assigned(P) then
  begin
    PInteger(P)^ := Length(Value);
    System.Move(Value,Pointer(PChar(P) + SizeOf(Integer))^,SizeOf(TBasic)*Length(Value));
  end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var H:Integer;
   P:Pointer;
   Q:PBasicPLU;
   Len:Word;
   I:Integer;
begin
Test(H);
if (H>0) then
begin
  P:=GlobalLock(H);
  Len := PInteger(P)^;
  GetMem(Q,SizeOf(TBasic)*Len);
  Q^:=PBasicPLU(PChar(P) + SizeOf(Integer))^;
    for i:=0 to Len-1 do
    begin
      Memo1.Lines.Add(Q^[i].Line);
      Memo1.Lines.Add(IntToStr(Q^[i].Id));
    end;
  FreeMem(Q);
  GlobalUnlock(H);
  GlobalFree(H);
end;
end;


GanibalLector   (2005-12-06 23:45:00) [19]

> Мем лик же возникает в любом случае.
Нет никакого мемлика! Ни в D5 ни в D7.

>Или ты представляешь как они работают?
Представляю.

> тогда, объясни мне пожалуйста - почему твой код не вызывает av?
А с чего он должен вызывать AV??? Был пример в книге. Сперва я попробовал передавать Integer и структуру...все получилось. Ну,а потом массив. А проблемы возникали из-за указателей.

> программирование методом тыка - это конечно метод..  но ни к чему хорошему он не приводит.
Я с тобой согласен. Знаешь,я учусь сам(в основном по книгам) и это я тебе уже говорил.Да,есть у меня некоторые пробелы в знаниях :( Лучше бы литературу порекомендовал!


jack128   (2005-12-06 21:55:00) [20]

GanibalLector ©   (06.12.05 19:00) [13]
>Бред. Если скомпилируешь с $R+ то глюки полезут из всех щелей.
Я этого не заметил.

Да, был не прав. Глюки должны полезть в том случае, если в первых 4 байтах памяти, выденой GetMem'ом не будут равны nil'у или же (тут еще несколько почти невероятных, отличии от первого вариантов). Мем лик же возникает в любом случае.  Еще раз, если ты не представляешь, как работают дин массивы - откажись от них. Или ты представляешь как они работают? тогда, объясни мне пожалуйста - почему твой код не вызывает av?

ps программирование методом тыка - это конечно метод..  но ни к чему хорошему он не приводит.


Страницы:   1 2

Наверх

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