• 0
Вадим Смоленский

Детский вопрос про область видимости переменной

Вопросы

Неловко спрашивать о таком на третьем десятке лет программирования на Delphi, но всё же спрошу. Вот предельно простой код:

program MyProgram;

uses
  MyUnit in 'MyUnit.pas' {MyForm};

var MyVariable: Boolean=False;

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TMyForm, MyForm);
  Application.Run;
end.

Как мне обратиться к переменной MyVariable из юнита MyUnit?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 ответов на этот вопрос

  • 0

Вынеси эту переменную в отдельный модуль 'MyVariableUnit.pas' и добавь его во все места, где нужно обращаться к переменной

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
30 минут назад, rareMax сказал:

Вынеси эту переменную в отдельный модуль 'MyVariableUnit.pas' и добавь его во все места, где нужно обращаться к переменной

Неужели нет более простого решения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
unit SharedGlobals;

interface

const
  ConstMyConstant = 30;

type
  TMyType = record
    AValue : String;
  end;

var
  MyVariable: Boolean=False;

  function MyFunction(AValue : String) : String;

implementation

function MyFunction(AValue : String) : String;
begin

end;

end.

И использование этого:

unit Unit1;

interface

uses
  SharedGlobals,
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs;

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

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormCreate(Sender: TObject);
begin
  АMyType.AValue:=ConstMyConstant;
  MyFunction(АMyType.AValue);
end;

end.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
15 часов назад, Вадим Смоленский сказал:

Выходит, только так, а напрямую нельзя.

Вы бы раскрыли смысл своего вопроса такого обращения к переменной, тогда может кто-то и подскажет решение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
4 часа назад, GASCHE сказал:

Вы бы раскрыли смысл своего вопроса такого обращения к переменной, тогда может кто-то и подскажет решение.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Обычно я делаю класс TCore, в котором все необходимое и настройки и переменные, я стараюсь формы и логику всегда отделять (раньше для Windows я вообще отделял логику и ядро в DLL ). Формы нужны только для отображения содержимого. Этот класс создаю в dpr до всех форм, Core соответсвенно в отдельном модуле, и глобальная переменная gCore там же в interface. Этот Core.pas подключаю уже везде. Это очень практично.

Изменено пользователем ENERGY

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Существует (если нельзя, но очень хочется, то можно). Правда проверял его работоспособность в VCL, в FM проверьте сами.

program Project2;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1};

var
  MyVariableInt: Integer;
  MyVariableBool: Boolean;
  MyVariableStr: string;

exports
  MyVariableInt,
  MyVariableBool,
  MyVariableStr;

{$R *.res}

begin
  MyVariableInt := 456;
  MyVariableBool := True;
  MyVariableStr := 'qwerty'#0;

  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
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)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  i: ^Integer;
begin
   i := GetProcAddress(HInstance, 'MyVariableInt');
   if Assigned(i) then
      ShowMessage(IntToStr(i^));

   i := GetProcAddress(HInstance, 'MyVariableBool');
   if Assigned(i) then
      ShowMessage(BoolToStr(Boolean(i^)));

   i := GetProcAddress(HInstance, 'MyVariableStr');
   if Assigned(i) then
      ShowMessage(PChar(i^));
end;

end.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Ну, подобным макаром можно и константы изменять)))

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Можно, и что? Вопрос был "как?", решение дано, вроде никаких противоречий нет...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

Это был не наезд)
Вы правы, можно, просто метод не совсем стандартный, мягко говоря)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0

@estra Так лучше не делать, т.к. решение не кроссплатформенное.  Не пойму что мешает автору завести отдельный pas модуль, например GlobalConst.pas и там объявить эту глобальную переменную и затем подключать этот модуль куда угодно. Это надуманная проблема. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
30 минут назад, ENERGY сказал:

@estra Так лучше не делать, т.к. решение не кроссплатформенное.  Не пойму что мешает автору завести отдельный pas модуль, например GlobalConst.pas и там объявить эту глобальную переменную и затем подключать этот модуль куда угодно. Это надуманная проблема. 

А я могу понять автора, хотя и с оговоркой.

Вы правы, способ не кроссплатформенный, но мы и не знаем, под какую ОС пишет ТС. Если под Винду, то почему бы и нет. Если нужно кроссплатформенное решение, то GlobalConst.pas  прекрасно подойдет, никто не спорит.

Но, подобными вопросами полезно задаваться и решать их в познавательных и исследовательских целях, чтобы лучше узнать инструмент, который используешь в работе. ТС не знал такого способа, теперь узнает, прокачает свои скилы, разве ж это плохо)))

Да и даже чисто с практической точки зрения, бывают задачи, которые просто невозможно решить, не прибегая к хакам. Так что знать о них нужно, но применять с умом и осторожностью, ибо они не панацея!!!

Изменено пользователем estra

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
2 часа назад, estra сказал:

в FM проверьте сами

Проверил, в FMX под Windows  не работает. После выполнения GetProcAddress отладчик показывает, что i=nil.

Да и бог с ним, что не работает. Я вижу, что тривиального решения нет - именно это и хотел узнать. А способ с отдельным юнитом меня вполне устраивает.

Изменено пользователем Вадим Смоленский

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты
  • 0
4 минуты назад, Вадим Смоленский сказал:

Проверил, не работает. После выполнения GetProcAddress отладчик показывает, что i=nil.

Да и бог с ним, что не работает. Я вижу, что тривиального решения нет - именно это и хотел узнать. А способ с отдельным юнитом меня вполне устраивает.

Значит не под Windows проверяли, ибо у меня под винду все работает...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти

  • Последние посетители   0 пользователей онлайн

    Ни одного зарегистрированного пользователя не просматривает данную страницу