Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 21.07.2009, 13:50   #1
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
Лампочка экспорт функций и процедур из exe файла

можете, пожалуйста, привести пример?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 21.07.2009, 14:04   #2
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

Точно так же, как и в dll

Код:
procedure one(p: pchar);
begin
  MessageBox(0,p,'',0);
end;

function two(foo:integer):integer;
begin
  two:=foo*2;
end;

exports one, two;
пыщь
JTG вне форума Ответить с цитированием
Старый 21.07.2009, 14:23   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

спасибо за ответ

но я понял что не правильно сформулировал вопрос
нужно чтото типа API к моей программе
то есть получение данных из нее и отправка данных в неё(передача команд и тд...запросы и прочее)

заранее спасибо
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 21.07.2009, 14:24   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата из Delphi World
Цитата:
В DPR файле совершенно обычного проэкта дельфи можно указать функцию (процедуру) и объявить ее как экспортируемую - синтаксис точно такой-же как при создании стандартной DLL. С таким довеском EXE совершенно нормально компиллируется и работает и как EXE и как DLL (т.е. из нее можно импортировать описанные функции). Зачем это нужно? Была одна задача - делал консоль которая связывала воедино несколько приложений, так экспортные функции позволяли существенно расширять функциональность комплекса. Правда такой EXE все же имеет недостаток - EXE упаковщики сохраняют исполняемую часть и неправильно упаковывают экспортированную...
Цитата:
то есть получение данных из нее и отправка данных в неё
Прикрути к проге СОМ-сервер.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.07.2009, 00:30   #5
BaronTreep
Форумчанин
 
Регистрация: 29.05.2009
Сообщений: 320
По умолчанию

А можно уточняющий пример насчет exe-like-dll? У меня получалось на Си, а тут:

Код:
procedure one(p : pchar); export; stdcall; // Кстати cdecl и pascal тоже не спасают
begin
  MessageBox(0, p, '', 0);
end;

exports one name 'one';
В итоге Access Violation по нулевому адресу.
BaronTreep вне форума Ответить с цитированием
Старый 22.07.2009, 09:17   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Неее. там не все так гладко будет...
А чего именно из EXE нужно?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 22.07.2009, 10:53   #7
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

Вот так вроде
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  oneProc: procedure (p: pchar) stdcall;
  twoProc: function (foo:integer):integer stdcall;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var lib:HModule;
begin
 lib := LoadLibraryEx('e:\копия project1.exe', 0, DONT_RESOLVE_DLL_REFERENCES);
 if not Win32Check(longbool(lib)) then exit;

 oneProc := GetProcAddress(lib,'one');
 if not Win32Check(longbool(@oneProc)) then exit;

 twoProc := GetProcAddress(lib,'two');
 if not Win32Check(longbool(@twoProc)) then exit;

 oneProc( pChar(IntToStr(twoProc(1))) );
end;

procedure one(p: pchar); stdcall;
begin
  MessageBox(0,p,'Тест',0);
end;

function two(foo:integer):integer; stdcall;
begin
  two:=foo*2;
end;

exports one, two;

end.
Экзешник с экспортом должен иметь секцию релоков (делфи их везде пихает) и его нельзя грузить статически или через LoadLibrary, т.к. при этом загрузчик ожидает увидеть в точке входа функцию DllMain, которая обязана вернуть ненулевое значение, а её нет.
Использовать модель вызова stdcall вообще-то не обязательно, просто чтоб народ не путать, если кто-то захочет импортировать функцию
пыщь

Последний раз редактировалось JTG; 22.07.2009 в 15:15.
JTG вне форума Ответить с цитированием
Старый 25.07.2009, 14:07   #8
BaronTreep
Форумчанин
 
Регистрация: 29.05.2009
Сообщений: 320
По умолчанию

Точно, DllMain то нет. Почти работает - создал один прожект:

Код:
  oneProc: procedure (p: pchar) stdcall;

procedure TForm1.FormCreate(Sender: TObject);
var
 lib : HModule;
begin
 lib := LoadLibraryEx('Project1.exe', 0, DONT_RESOLVE_DLL_REFERENCES);
 if not Win32Check(longbool(lib)) then exit;
 oneProc := GetProcAddress(lib,'one');
 if not Win32Check(longbool(@oneProc)) then exit;
end;

procedure one(p: pchar); stdcall;
begin
  MessageBox(0, p, 'Wath', 0);
end;

exports one;
И второй:

Код:
  oneProc: procedure (p: pchar) stdcall;

procedure TForm1.FormCreate(Sender: TObject);
var lib:HModule;
begin
 lib := LoadLibraryEx('Project1.exe', 0, DONT_RESOLVE_DLL_REFERENCES);
 if not Win32Check(longbool(lib)) then exit;

 oneProc := GetProcAddress(lib,'one');
 if not Win32Check(longbool(@oneProc)) then exit;

 oneProc( '' );
end;
Вызов во втором работает только если в первом есть TForm1.Create с LoadLibraryEx и т.д. - парадокс, опять же в заголовке MessageBox непонятно что.

Вызов процедуры в Project1 из самое себя сработал только так:

Код:
type
  oneProc = procedure (p: pchar) stdcall;

var
  onePr : oneProc;
  lib : HModule;

procedure one(p: pchar); stdcall;
begin
  MessageBox(0, p, 'Wath', 0);
end;

exports one;

procedure TForm1.FormCreate(Sender: TObject);
begin
 lib := LoadLibraryEx('Project1.exe', 0, DONT_RESOLVE_DLL_REFERENCES);
 onePr := GetProcAddress(lib, 'one');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 onePr('1');
end;
BaronTreep вне форума Ответить с цитированием
Старый 25.07.2009, 15:01   #9
BaronTreep
Форумчанин
 
Регистрация: 29.05.2009
Сообщений: 320
По умолчанию

Код:
// needtesting.c

#include <stdio.h>
#include <windows.h>

__declspec(dllexport) void Check(char * Capt, char * Mess)
{
  MessageBox(0, Mess, Capt, SW_SHOW);
}

void main()
{
  HMODULE h;
  void (*fun)();

  if ((h = LoadLibrary("needtesting.exe")) 
    && (fun = (void (*)()) GetProcAddress(h, "Check")))
      fun("English", "Русский");
}
В Си обычная LoadLibrary работает (?)

Последний раз редактировалось BaronTreep; 25.07.2009 в 15:03.
BaronTreep вне форума Ответить с цитированием
Старый 25.07.2009, 22:14   #10
JTG
я получил эту роль
Старожил
 
Аватар для JTG
 
Регистрация: 25.05.2007
Сообщений: 3,694
По умолчанию

Короче это всё изврат. При попытке экзешника загрузить самого себя через LoadLibrary, она вернёт дескриптор уже загруженного модуля, это легко проверить, добавив в Button1Click
Код:
ShowMessage( format('HInstance 0x%x' + #13 + 'Loaded at 0x%x', [hinstance, lib]));
В этом случае GetProcAddress нормально отработает и фактически вернёт адрес функции в самой программе. Если грузить самого себя через LoadLibraryEx - результат получается непредсказуем, и фиг его знает что там происходит со счётчиком ссылок, работает через раз


Теперь что будет, если экспорт в одном экзешнике, а вызываем его функции из другого:
в МСДН мелким шрифтом написано "If the specified module is an .exe file, static imports are not loaded": при загрузке секция импорта не заполняется и вместо того же MessageBox в экспортируемой функции будут адрес, ведущий в космос. Если в функции чистая арифметика и т.д. - всё ок, обращение к импорту - ошибка. Чтоб подгрузить оттуда другой модуль, видимо придётся "по Рихтеру" находить kernel32.dllи работать через LoadLibrary/GetProcAddress (или же передавать их адреса параметрами функции), или каким-то образом вручную заполнять импорт.
пыщь

Последний раз редактировалось JTG; 25.07.2009 в 22:28.
JTG вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
использование процедур и функций! ...Оленька... Паскаль, Turbo Pascal, PascalABC.NET 0 24.12.2008 15:33
Глобальность функций и процедур rivers Общие вопросы Delphi 5 01.08.2008 20:35
Параметры процедур и функций shurik_7866 Общие вопросы Delphi 8 10.12.2007 19:49