Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.01.01;
Скачать: CL | DM;

Вниз

Как получить адрес процедур собственной программы (по названию п)   Найти похожие ветки 

 
AllDontFire   (2005-10-29 15:24) [0]

Пробовал GetProcAddress, но, насколько я понял, так нельзя, это только для Dll?


 
begin...end ©   (2005-10-29 15:48) [1]

> AllDontFire   (29.10.05 15:24)

Это возможно и для EXE, но нужные подпрограммы нужно включить в список exports.


 
wp2   (2005-10-29 15:52) [2]

А если попробовать @


 
raiks   (2005-10-29 19:05) [3]

procedure DoSomething;
begin

end;

var p: Pointer;
begin
 p:=@DoSomething;
 ShowMessage("Адрес DoSomething: " + IntToStr(Cardinal(p)));
end;


 
AllDontFire   (2005-10-29 22:15) [4]

raiks,
p:=@DoSomething - -это понятно.
Но мне нужно найти адрес, передавая символьное название процедуры как в
GetProcAddress.


 
wp2   (2005-10-30 01:39) [5]

Удалено модератором


 
raiks   (2005-10-30 02:29) [6]

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


 
Джо ©   (2005-10-30 02:37) [7]


>  [4] AllDontFire   (29.10.05 22:15)

Разумумный ответ см.  [1] begin...end ©   (29.10.05 15:48)

Другой подход - сделать процуры published-методами какого-нибудь класса, скомпилированным с директовой {$M+}. Тогда можно искать методы по имени.

Непонятно только, зачем это нужно? Может, если объяснить конкретную задачу, найдется более оптимальное решение.


 
Джо ©   (2005-10-30 02:01) [8]

Делать мне, наверное, нечего.

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

Подход с получением адреса экспортируемой функции.

program Project2;

{$APPTYPE CONSOLE}

uses
 Windows,
 SysUtils;

// эта процедура экспортируется
procedure DoSomething;
begin
 WriteLn ("DoSomething called.");
end;

// эта процедура экспортируется
procedure DoSomethingElse;
begin
 WriteLn ("DoSomethingElse called.");
end;

// а эта процедура НЕ экспортируется
procedure YouCannotCallMe;
begin
 WriteLn ("You should not see this message.");
end;

// экспортируем нужные функции
exports
 DoSomething,
 DoSomethingElse;

var
 ProcName: string;
 Proc: procedure;

begin
 ProcName := ParamStr(1);

 if ProcName = "" then
 begin
   WriteLn ("Specify a procedure name");
   Exit;
 end;

 proc := GetProcAddress(0,PChar(ProcName));
 if Assigned(Proc) then
   Proc()
 else
   WriteLn ("Procedure ",ProcName," not found in executable.");

 ReadLn;
end.

---
Подход с получением адреса published-метода класса.

program Project2;

{$APPTYPE CONSOLE}

uses
 SysUtils,
 TypInfo;

type

 TCommander = class
 public
   procedure YouCannotCallMe;
 published
   procedure DoSomething;
   procedure DoSomethingElse;
 end;

{ TCommander }

procedure TCommander.DoSomethingElse;
begin
 WriteLn ("DoSomethingElse called.");
end;

procedure TCommander.DoSomething;
begin
 WriteLn ("DoSomething called.");
end;

procedure TCommander.YouCannotCallMe;
begin
 WriteLn ("You should not see this message.");
end;

var
 ProcName: string;
 Proc: procedure;
 Commander: TCommander;

begin
 ProcName := ParamStr(1);

 if ProcName = "" then
 begin
   WriteLn ("Specify a procedure name");
   Exit;
 end;

 Commander := TCommander.Create;
 try
   Proc := Commander.MethodAddress (ProcName);
   if Assigned (Proc) then
     Proc ()
   else
     WriteLn ("Unknown command requested.");
 finally
   Commander.Free;
 end;

 ReadLn;
end.


П.С. Надеюсь, пригодится.

И -- я наврал насчет директивы {$M+}, сейчас вожусь с RTTI и немного заработался, видимо :(


 
Джо ©   (2005-10-30 02:34) [9]

Мда... спешка к добру не приводит. Исправления во второй пример, позорные:

var
...
Proc: procedure of object;
...
   TMethod(Proc).Code := Commander.MethodAddress (ProcName);
   TMethod(Proc).Data := Commander;


 
AllDontFire   (2005-10-30 11:23) [10]

Спасибо, всё понятно.
Ну это нужно, например, когда, в зависимости от какого-либо входного параметра, необходимо запустить опр. процедуру. Можно конечно выйти из положения через IF, но, а если много вариантов входных параметров, то и "Ифов" будет много, а это не удобно я думаю.


 
raiks   (2005-10-30 13:39) [11]

Джо

Ради интереса опробовал 1-й ваш пример. Работает :) Потом решил проделать то же самое с другим *.exe, в раздел exports которого добавлена соответствующая строка. Файл нормально загрузился с помощью LoadLibrary, адрес процедуры DoSomething тоже нашелся, но при попытке вызвать ее вылезло неизбывное сообщение об Access Violation. Я так понимаю, это связано с атрибутами доступа к памяти? Можно ли это исправить?

-----------Project1.exe------------

program Project1;
uses Windows;

procedure DoSomething;
begin
 MessageBox(0, "Hello from DoSomething()", nil, MB_ICONWARNING);
end;

exports
 DoSomething;

begin
end.

-----------Project2.exe------------

var
 hLib: THandle;
 DoSmth: procedure;
begin
 hLib:=LoadLibrary("f:\project1.exe");
 if hLib<>0 then
   begin
     MessageBox(0, "Module Project1 was loaded!", nil, MB_ICONWARNING);
     @DoSmth:=GetProcAddress(hLib, "DoSomething");
     if @DoSmth<>nil then
       begin
         MessageBox(0, "Procedure DoSomething() was found!", nil,   MB_ICONWARNING);
         DoSmth;
      end;
     FreeLibrary(hLib);
   end;
end;


 
Digitman ©   (2005-10-31 10:17) [12]


> raiks   (30.10.05 13:39) [11]


> связано с атрибутами доступа к памяти?


нет, это связано с совершенно иным - с обработкой загрузчиком таблицы релокации и инициализацией pe-модуля


 
Polevi ©   (2005-10-31 10:47) [13]

можно сделать через FindClass



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

Текущий архив: 2006.01.01;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.04 c
14-1133939182
КаПиБаРа
2005-12-07 10:06
2006.01.01
Пара задач с числами


1-1133680905
Элеонора
2005-12-04 10:21
2006.01.01
GetIconMetaPict


4-1130502177
Jimm
2005-10-28 16:22
2006.01.01
Убрать границы у combobox, button ...


1-1133518094
alsov
2005-12-02 13:08
2006.01.01
Компилирование группы проектов из командной строки


1-1133518175
.ruslan
2005-12-02 13:09
2006.01.01
812a456f975t149r