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

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

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

Восстановить пароль
Повторная активизация e-mail

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

Ответ
 
Опции темы Поиск в этой теме
Старый 30.07.2012, 00:32   #1
WhiskasTM
Подтвердите свой е-майл
 
Регистрация: 11.04.2012
Сообщений: 85
По умолчанию Передать че-нибудь в DLL / Из DLL прочитать переменную EXE

Случился вынос мозга, если вызывать функции и процедуры из DLL то все понятно, через них можно передавать всякие там цифры, тексты и т.п.

А как в обратную сторону? У меня в exe есть глобальная переменная, текст, как мне передать её в процедуру в dll т.е. чтобы dll подхватила это и начала там че-то делать с этим.

EXE:
Код:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    STR:string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
 STR:=Edit1.Text;
 SendtoDLL(STR) //???
end;

end.
DLL:
Код:
library Project2;

uses
  System.SysUtils,
  System.Classes,
  Vcl.Dialogs;

{$R *.res}

procedure DoSomethingProc;stdcall;
var
S:string;
begin
 S:=GetFromExe(STR); //??? Как переменную STR из exe-шника сюда задекларировать?
 S:=S+'abc'+'@'+'xyz';
end;

begin
end.
WhiskasTM вне форума Ответить с цитированием
Старый 30.07.2012, 01:49   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вспомнить про аргументы функций и не искать ж**у себе.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 30.07.2012, 02:31   #3
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

Цитата:
S:=GetFromExe(STR); //??? Как переменную STR из exe-шника сюда задекларировать?
Что за бред?
VintProg вне форума Ответить с цитированием
Старый 30.07.2012, 02:51   #4
WhiskasTM
Подтвердите свой е-майл
 
Регистрация: 11.04.2012
Сообщений: 85
По умолчанию

Цитата:
Сообщение от Пепел Феникса Посмотреть сообщение
вспомнить про аргументы функций и не искать ж**у себе.
и ни хера ниче не понял, пофиг, по этим тэгам уже че-то полезное гугл выдал.
Цитата:
Сообщение от VintProg Посмотреть сообщение
Что за бред?
Образно же показано. Надо бы нюансы dll найти, че то может все вверх на голову поставил
WhiskasTM вне форума Ответить с цитированием
Старый 30.07.2012, 05:00   #5
VintProg
not
Участник клуба
 
Аватар для VintProg
 
Регистрация: 27.06.2009
Сообщений: 1,399
По умолчанию

Цитата:
вспомнить про аргументы функций и не искать ж**у себе.
Какого жору в себе не искать?

Может получить в длл, значение переменной из exe? А что собственно такое длл? Это тот же кусок кода, который грубо говоря "Аттачиться" в exe при загрузке. Это как бы одно целом можно так сказать.

ну это не трудно, сперва узнаем адрес глобальной переменной в exe.

к примеру в длл, есть функция:

Код:
function GetValue : integer;
begin
  Result := PInteger( $00AA0C  )^;   // Это все считывается из одного адресного пространства.
end;
где твой адрес заместо: $00AA0C


Цитата:
procedure DoSomethingProc;stdcall;
stdcall - не обязательно писать, в настройках и так по умолчанию все стоит.

Как получить адрес переменной в exe?

Легко: x := Cardinal(@value); Value - где ваша переменная, в x - будет занесен адрес. Это как бы приведение подобно в C++ reinterpret_cast.

У меня почему-то нету типа PInteger?

ну это не трудно объявить вверху:

Код:
type
 PInteger = ^Integer;
Вот теперь есть.

Важно! Ваша exe должна обязательно загрузить длл

хммм, не пойму зачем такой индийский код, вроде на правки, на инжекты различного типа не похоже...
Возможно экскременты какие-то от рук студентов (проект вынос мозга), а хотя ладно, занимайтесь (но что такое dll надо по учить еще по лучше). =)

Последний раз редактировалось VintProg; 30.07.2012 в 05:26. Причина: Да борщик с капусткой, вариться туда сюда бегаю, дописываю ответы,но борщик не красный? Ладно разберусь сам буду отлаживать.
VintProg вне форума Ответить с цитированием
Старый 30.07.2012, 06:44   #6
WhiskasTM
Подтвердите свой е-майл
 
Регистрация: 11.04.2012
Сообщений: 85
По умолчанию

VintProg, сложно=)

Походу я хотел иметь суперглобальную переменную, к которой раз и обратился, и её значение(integer) хоть куда хоть где пиши. Это значение бы хранилось всегда в одном месте. Наверное именно это.

Короче я не знаю че мудрил, я все сделал, Значение offset определяется в процедуре dll(оно неизвестно заранее), потом переносится в X уже в exe-шники чтобы я мог фигачить его в едиты, листбоксы и прочее.
Правда, можно сразу брать из dll, но че меня так прет я не знаю

app:
Код:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Edit2: TEdit;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    X:integer;
  end;
type CustomArrayOfBytes = array of byte;

var
  Form1: TForm1;
implementation

{$R *.dfm}

function bytetostr(bytes: array of byte): string;
   stdcall; external 'Project2.dll';

function __ReadBytes(FileName:string;Length:integer):CustomArrayOfBytes;
    stdcall; external 'Project2.dll';

function __GetOffsetValue:integer;stdcall;external 'Project2.dll';

procedure __WriteBytes(FileName:string);stdcall;external 'Project2.dll';

procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text:=bytetostr(__ReadBytes('D:\test.123',20));
X:=__GetOffsetValue();
Edit2.Text:=inttostr(X);
end;



procedure TForm1.Button2Click(Sender: TObject);
begin
__WriteBytes('D:\test.123');
end;

end.
вдд
Код:
library Project2;

uses
  ShareMem,
  System.SysUtils,
  System.Classes;

  type CustomArrayOfBytes = array of byte;
{$R *.res}
var
Offset:integer;

function __GetOffsetValue:integer;stdcall;
begin
  Result:=Offset;
end;

function bytetostr(bytes: array of byte): string;stdcall;
const
BytesHex: array[0..15] of char =
    ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F');
var
  i, len: integer;
begin
len := Length(bytes);
SetLength(Result, len * 2);
for i := 0 to len - 1 do
begin
 Result[i * 2 + 1] := BytesHex[bytes[i] shr 4];
 Result[i * 2 + 2] := BytesHex[bytes[i] and $0F];
end;
end;


{-I}
function __ReadBytes(FileName:string;Length:integer):CustomArrayOfBytes;stdcall;
var
f:file of byte;
a:CustomArrayOfBytes;
bytes1 :array [0..3] of byte;
label again;
begin
  Offset:=0;
  AssignFile(f,FileName);
  Reset(f);
  begin
     again:
     inc(Offset,1) ;
     Seek(f,Offset);
     BlockRead(f,bytes1, 4);
     if bytetostr(bytes1)<>'AAFFFF90' then goto again
else
begin
Seek(f,Offset);
Setlength(a,Length);
BlockRead(f,a[0],Length);
Result:=a;
CloseFile(f);
end;
end;
end;

procedure __WriteBytes(FileName:string);stdcall;
const
arraybyte:array [0..3] of byte = ($99,$99,$99,$99);
var
f:file of byte;
begin
  AssignFile(f,FileName);
  Reset(f);
  Seek(f,Offset);
  BlockWrite(f,arraybyte,4);
  CloseFile(f);
end;

exports __ReadBytes, bytetostr,__GetOffsetValue,__WriteBytes;
begin
end.
Ах, да, увидел в чем мой тупик, в функции __WriteBytes есть строка Seek(f,Offset), ясень пень из глобальной offset берется, в которой уже лежит. А я хочу чтобы из X бралось, я туда новый адресс суну. Вот, надо перегнать из X обратно в offset.

Налево вашу)))) Пойдет.
Код:
procedure __WriteBytes(FileName:string;X_Offset_New:integer);stdcall;external 'Project2.dll';

procedure TForm1.Button2Click(Sender: TObject);
begin
X:=900;
__WriteBytes('D:\test.123',X);
end;

DLL....

procedure __WriteBytes(FileName:string;X_Offset_New:integer);stdcall;
const
arraybyte:array [0..3] of byte = ($99,$99,$99,$99);
var
f:file of byte;
begin
  AssignFile(f,FileName);
  Reset(f);
  Seek(f,X_Offset_New);
  BlockWrite(f,arraybyte,4);
  CloseFile(f);
end;

Последний раз редактировалось WhiskasTM; 30.07.2012 в 07:01. Причина: Курил)
WhiskasTM вне форума Ответить с цитированием
Старый 30.07.2012, 14:47   #7
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Рыдаю. Просто рыдаю.

Волшебное слово - Callback (a.k.a. функция обратного вызова).

Код:
library Project2;

uses
  Windows,
  SysUtils;

type
  TCallbackProc = function: Integer; stdcall;

var
  GetValue: TCallbackProc;

procedure Init(const ACallback: TCallbackProc); stdcall;
begin
  GetValue := ACallback;
end;

function DoSomething: Integer; stdcall;
begin
  Result := GetValue * 2;
end;

exports
  DoSomething,
  Init;

end.
Код:
unit Unit1;

...

function Callback: Integer; stdcall;
begin
  Result := Form1.Tag;
end;

procedure TForm1.Button1Click(Sender: TObject);
type
  TCallbackProc = function: Integer; stdcall;
  TInitProc = procedure(const ACallback: TCallbackProc); stdcall;
  TDoSomethingProc = function: Integer; stdcall;
var
  Lib: HMODULE;
  Init: TInitProc;
  DoSomething: TDoSomethingProc;
begin
  Lib := LoadLibrary('Project2.dll');  
  Win32Check(Lib <> 0);
  try
    Init := GetProcAddress(Lib, 'Init');
    Win32Check(Assigned(Init));
    Init(Callback);
    DoSomething := GetProcAddress(Lib, 'DoSomething');
    Win32Check(Assigned(DoSomething));

    Tag := 5;
    Caption := IntToStr(DoSomething); // выведет '10'
  finally
    FreeLibrary(Lib);
  end;
end;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 30.07.2012, 17:07   #8
WhiskasTM
Подтвердите свой е-майл
 
Регистрация: 11.04.2012
Сообщений: 85
По умолчанию

Мдаа, волшебство то что нужно. Спс. Кстати я че то не подумал про LoadLibrary, а то все external да external
WhiskasTM вне форума Ответить с цитированием
Старый 30.07.2012, 18:01   #9
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Это не имеет значения.

Без LoadLibrary:
Код:
unit Unit1;

...

type
  TCallbackProc = function: Integer; stdcall;

procedure Init(const ACallback: TCallbackProc); stdcall; external 'Project2.dll';
function DoSomething: Integer; stdcall; external 'Project2.dll';

...

function Callback: Integer; stdcall;
begin
  Result := Form1.Tag;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Init(Callback);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Tag := 5;
  Caption := IntToStr(DoSomething); // выведет '10'
end;
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 02.08.2012, 13:33   #10
IliaIT
Форумчанин
 
Аватар для IliaIT
 
Регистрация: 17.03.2009
Сообщений: 977
По умолчанию

ой а чего исходящие переменные не работают из длл???

то есть. где s_lok входящая а s2_loc исходящая.
Код:
library Project2;

uses
  SysUtils,
  Classes;

{$R *.res}
procedure DoSomethingProc (s_lok:integer; var s2_loc:integer);stdcall;
begin
  s2_loc:=s_lok+1;
end;
exports DoSomethingProc;
begin
end.
и описание и вызов соответственно из основного кода.
Код:
procedure DoSomethingProc (s_lok:integer; var s2_loc:integer);stdcall;external 'Project2.dll';

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
s1:integer;
begin
  DoSomethingProc(45,s1);
  Button1.Caption:=inttostr(s1);
end;

end.
Интуитивно понятный интерфейс - это такой интерфейс, для работы с которым нужна недюжинная интуиция.
IliaIT вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как Передать Переменную В Dll Из Вызывающей Программы? system21rus C++ Builder 0 16.04.2012 11:47
прочитать файл *.dll Ципихович Эндрю Свободное общение 15 06.11.2011 16:24
Запуск Load.dll (бывшая Load.exe) в дереве проц-ов, Как запустить прогой на C# .dll-ку kapustin Общие вопросы .NET 10 23.09.2009 22:20
из .exe TBitMap передать в DLL(форма) lexaltd Мультимедиа в Delphi 13 14.07.2009 17:47
взять переменную из dll Roof Общие вопросы Delphi 15 27.08.2008 16:40