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

Вниз

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

 
GanibalLector ©   (2005-12-04 17:33) [0]

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

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;


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


 
jack128 ©   (2005-12-04 18:05) [1]

GanibalLector ©   (04.12.05 17:33)
Но вот не получается с кодом :(

Хорошее объяснение. И главное очень подробное.

ps Почему GlobalLock вызываешь два раза, а GlobalUnlock - только один??

pps Вообще мне не нравится твой подход.


 
begin...end ©   (2005-12-04 18:27) [2]

> GanibalLector ©   (04.12.05 17:33)

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

Функции, находящейся в DLL, передаются 2 параметра -- указатель на заранее выделенную область памяти, в которую нужно поместить данные, и длина этой области (var-параметр). Если указатель равен nil, то функция ничего не помещает в буфер, а во втором параметре возвращает требуемую длину буфера.

EXE вызывает функцию вначале с nil-указателем, получая необходимую длину буфера, выделяет буфер и вызывает функцию снова -- с указателем на готовый буфер.

Типичная схема для многих API-функций. Почему бы и здесь не сделать так же?


 
Юрий Зотов ©   (2005-12-04 19:38) [3]

А еще проще использовать ShareMem и SetLength. Не создавая самому себе лишних проблем.


 
Набережных С. ©   (2005-12-04 20:12) [4]

Или экспортировать из ДЛЛ пару функций выделения и освобождения памяти.

Или использовать IMalloc или функции-оболочки вокруг его системной реализации CoTaskMemAlloc etc

Или делать COM-сервер и реализовать интерфейс-перечислитель.

Или использовать IMardhal и реализовать объект, передаваемый "по значению".

И все эти способы, как и [2], дают большую или меньшую незаисимость от среды разработки.


 
GanibalLector ©   (2005-12-04 21:56) [5]

2 begin...end ©   (04.12.05 18:27) [2]
>Типичная схема для многих API-функций. Почему бы и здесь не сделать так же?
Хорошо...Вот бы на код посмотреть ;)


 
GanibalLector ©   (2005-12-05 12:21) [6]

Я продолжу свои мысли...вдруг кому-то будет интересно ;)
Так вот,усложним пример в [0] и будем передавать структуру.

type
  TBasic=packed record
    Id:Byte;
    Line : String[24];  
end;
PBasic = ^TBasic;

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

procedure TForm1.Button1Click(Sender: TObject);
var H:Integer;
    P:Pointer;
    Q:TBasic;
begin
Test(H);
if H>0 then
begin
  P:=GlobalLock(H);
  Q:=PBasic(P)^;
    Memo1.Lines.Add(Q.Line);
    Memo1.Lines.Add(IntToStr(Q.Id));
  GlobalUnlock(H);
  GlobalFree(H);
end;
end;


Данный код работает ;)

Ну,а теперь перейдем уже к массиву определенной  структуры.Т.е. к основной и заветной цели [0]. Итак :

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,10);
 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)+1);
 if HMem>0 then
 begin
   P:=GlobalLock(HMem);
   if Assigned(P) then System.Move(Value,P^,SizeOf(TBasic)*Length(Value));
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var H:Integer;
    P:Pointer;
    Q:TBasicPLU;
    i:Integer;
begin
 Q:=nil;
 Test(H);
 if H>0 then
 begin
   P:=GlobalLock(H);
   Q:=PBasicPLU(P)^;
   //Caption:=IntToStr(Length(Q)); тут вообще ужас :(
   for i:=0 to 9 do
   begin
     Memo1.Lines.Add(Q[i].Line);
     Memo1.Lines.Add(IntToStr(Q[i].Id));
   end;
   GlobalUnlock(H);
   GlobalFree(H);
 end;
end;


Как Вы понимаете этот код не работает.Даже не вижу причин для этого :(
И еще...если вместо цикла поставить

 Memo1.Lines.Add(IntToStr(Q[2].Id));
 Memo1.Lines.Add(Q[2].Line);

то результат будет правильным,но только на значениях от 2 до 9.
Может память выделяю неверно???


 
GanibalLector ©   (2005-12-05 12:23) [7]

2 begin...end ©   (04.12.05 18:27) [2]
>Типичная схема для многих API-функций. Почему бы и здесь не сделать так же?

Кстати,напомните оные. Запамятовал :( Хоть погляжу в генофонде...


 
jack128 ©   (2005-12-05 12:32) [8]

GanibalLector ©   (05.12.05 12:21) [6]
TBasicPLU = array of TBasic

GanibalLector ©   (05.12.05 12:21) [6]
  Q:=PBasicPLU(P)^;
  //Caption:=IntToStr(Length(Q)); тут вообще ужас :(


Ты где так научился?? Бред написал - ужас получил, всё закономерно.
procedure Test(var HMem:Integer);
var Value:TBasicPLU;
   P:Pointer;
   I:Integer;
begin
SetLength(Value,10);
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));
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));
    ClobalUnlock(P);
  end;
end;
end;

...
type
 TBasicArray = array[0..(MaxInt div SizeOf(TBasic)) - 1] of TBasic;
 PBasicArray = ^TBasicArray;
var
 Arr: PBasicArray;
 Len: Integer;
begin
Q:=nil;
Test(H);
if H>0 then
begin
  P:=GlobalLock(H);
  Len := PInteger(P)^; // получаем длину массива.
  Arr := Pointer(PChar(P) + SizeOf(Integer));
  Caption:=IntToStr(Len));
  for i:=0 to Len do
  begin
    Memo1.Lines.Add(Arr[i].Line);
    Memo1.Lines.Add(IntToStr(Arr[i].Id));
  end;
  GlobalUnlock(H);
  GlobalFree(H);
end;


PS
Вообще мне не нравится твой подход.(c)Я


 
jack128 ©   (2005-12-05 12:33) [9]

jack128 ©   (05.12.05 12:32) [8]
for i:=0 to Len - 1 do


 
GanibalLector ©   (2005-12-05 13:28) [10]

2 jack128
Спасибо!!!
А я тем временем сделал так :

function Test(var HMem:Integer):Word;
var Value:TBasicPLU;
    P:Pointer;
    I:Integer;
begin
 Result:=0;
 SetLength(Value,10);
 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)+1);
 if HMem>0 then
 begin
   P:=GlobalLock(HMem);
   if Assigned(P) then
   begin
     System.Move(Value,P^,SizeOf(TBasic)*Length(Value));
     Result:=Length(Value);
   end;
 end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var H:Integer;
    P:Pointer;
    Q:PBasicPLU;
    SizeArr:Word;
    I:Integer;
begin
 SizeArr:=Test(H);
 if (H>0) and (SizeArr>0) then
 begin
   P:=GlobalLock(H);
   GetMem(Q,SizeOf(TBasic)*SizeArr); // вот в чем дело !!!
   Q^:=PBasicPLU(P)^;
     for i:=0 to SizeArr-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;


 
jack128 ©   (2005-12-05 13:58) [11]

GanibalLector ©   (05.12.05 13:28) [10]
  GetMem(Q,SizeOf(TBasic)*SizeArr); // вот в чем дело !!!

Бред. Если скомпилируешь с $R+ то глюки полезут из всех щелей.  Оставь в покое динамические массивы, если не знаешь как они работают.


 
GuAV ©   (2005-12-05 16:39) [12]

см. [2], [3], [4] +
Кроме уже указанных подходов следует также упомянуть enumeration callback функции. В функцию dll передается функция приложения, которая будет вызванна для каждой записи. Преимущества этого подхода:
+ Нет выделения памяти в одном месте и освобожения в другом. При желании, нет вообще динамического выделения памяти.
+ Есть примеры в WinAPI - EnumXXX
+ Line м.б. PChar - это снимет ограничения на длину.
+ Эта dll м.б. использована из приложения на Delphi, C, и даже VB (при соблюдении stdcall и ограничения стандартными типами).


 
GanibalLector ©   (2005-12-06 19:00) [13]

2 jack128 ©
>Бред. Если скомпилируешь с $R+ то глюки полезут из всех щелей.
Я этого не заметил.Код прекрасно отработал на D5 и D7.

>вообще мне не нравится твой подход
А я и не говорил,что это мой подход! Это подход Тенцера.Взято у него в книге. Также автор предлагает использовать ф-цию CoTaskMemAlloc указанную в [4].

З.Ы. И еще,код в [8] не рабочий.


 
Cash ©   (2005-12-06 21:17) [14]

whatsup! Вмешаться можно? А... всеравно влез!

Предворю:
 В код на последующих постах не вглядывался,
 поэтому, если что, не ругать!

Замечу:
To GanibalLector ©:
 С построением записи TBasic полностью согласен,
 это хорошо, что она не ранжирована.
 А вот с этим:


   PBasicPLU = ^TBasicPLU;
   TBasicPLU = array of TBasic;


 категорически не согласен!
 Словами это объясняется так:
 "создадим указатель на масив {TBasicPLU = array of TBasic;},
  и еще создадим указатель на этот указатель,
  и будем его использовать.", по моему это странно!
 Работать то будет, но каряво!
 Код TBasicPLU = array of TBasic, создаст
 открытый масив, при этом переменная этого типа будет указателем.
 С этим типом хорошо работать с помощью функций:
   SetLength(variable,len1,len2,.......,lenN); - она создает N-мерный масив. (выделяет память в ОП)
   Finalize(variable); - она эту память вычищает и ставит variable в nil.

 Удобно? Мне - да. Особенно при том, что я частнько юзаю
 плагины для своих прог, а там такое иногда надо. Передать указатель в
 длл-овую функцию удобнее чем саму переменную, главное запретить
 изменение этого указателя (если обратного не нужно).

 Память под масив лучше выделять в основной проге, указатель
 сформируется в ее адресном пространстве, создай функцию,
 которая возвращает число необходимых элементов.
 Вызвай SetLength(parray,Extern_GetCount) для создания масива.
 Передавай указатель созданного масива во внешнюю функцию,
 которая его заполнит.
 Для просмотра длины масива можно воспользоваться функцией
 High(parray), которая вернет максимальный индекс элемента
 масива, делай High(parray)+1 для получения размера масива.
 Данные можно получить легко, как будто обращаешся к статическому
 масиву, легко и удобно parray[0] .. parray[High(parray)].
 И еще, уж чего чего, а со строками надо быть поосторожнее.
 В Pascal можно задать максимум 255 символов для сток,
 а в Delphi? Тоже 255? или 552? А мож 65536? и так тоже можно!
 Сторка в Делфи тоже является указателем! Поэтому, присваивая
 новое строковое значение прога создает для нее адрес в текущей
 секции ОП, то есть в области длл-ки, а прога туда глядеть не может!
 Поэтому, либо используй PChar тип строк, либо юзай юнтит ShareMem
 и кидай borlandmm.dll рядом с exe-шником (ShareMem надо подключить
 и к длл-ке и к DPR файлу. С этим юнитом ваабще все проблемы с
 разделенной памятью отвалятся, она станет нераздельная для длл-ки
 и для проги).


 
jack128 ©   (2005-12-06 21:55) [15]

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

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

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


 
GanibalLector ©   (2005-12-06 23:45) [16]

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

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

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

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


 
GanibalLector ©   (2005-12-06 23:53) [17]

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;



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

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

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


 
GanibalLector ©   (2005-12-07 02:06) [19]

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

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


 
Slym ©   (2005-12-07 06:24) [20]

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


 
Fay ©   (2005-12-07 07:30) [21]

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


 
Slym ©   (2005-12-07 07:37) [22]

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

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


 
Fay ©   (2005-12-07 07:42) [23]

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


 
jack128 ©   (2005-12-07 10:14) [24]

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

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

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

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


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

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


 
GanibalLector ©   (2005-12-07 21:18) [26]

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

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

А это идея ;)


 
jack128 ©   (2005-12-07 21:49) [27]

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

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


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

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

Look to (06.12.05 21:17) [14]


 
jack128 ©   (2005-12-08 15:56) [29]

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 22:00) [30]

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

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

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

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

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

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

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


 
jack128 ©   (2005-12-08 22:47) [31]

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
тоже имеют свое адресное пространство

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


 
jack128 ©   (2005-12-08 23:06) [32]

Вот, наваял спецом для тебя примерчик как писать в "блок памяти 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;


 
Alexander Panov ©   (2005-12-08 23:08) [33]

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


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


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

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



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

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

Наверх




Память: 0.58 MB
Время: 0.016 c
14-1134935788
QwertyKz
2005-12-18 22:56
2006.01.15
C# и дизайнер форм


6-1127994898
Cameron
2005-09-29 15:54
2006.01.15
проблема передачи через сокеты не могу передать больше 8 кб


6-1128346174
kay
2005-10-03 17:29
2006.01.15
Как сделать, чтобы при использовании InternetConnect и прочих...


14-1134661078
Bogdan1024
2005-12-15 18:37
2006.01.15
купил себе модем


14-1134541199
Жук
2005-12-14 09:19
2006.01.15
Запуск Д6





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский