Пишу компонент для вызова процедур посредством динамической загрузки модулей - в некотором роде аналог привычных многим исполняемых файлов C/C++, у которых есть процедураmainс параметрами командной строкиargc, argv.

Зачем? Это такой аналог майкрософтовского RunDll32, который умеет вызывать процедуры из библиотек. Для вызова процедур не требуется наличие BlackBox, нужен лишь загрузчик этих модулей. А далее за работу отвечает загруженный компонент, как типичная исполняемая программа.

У меня возникли проблемы с использованием модуля Meta.  Подробности (и сам вопрос) - ниже.

Цепочка вызова такова:
TestLoader (загрузчик модулей, исполняемый/EXE) - в него я буду передавать параметры с командной строки. В последствии этот модуль будет вызываться из исполняемого файла на XDS Oberon-2 (Windows/Linux).Loader (переработанный StdInterpreter) будет запускать соответствующие процедуры по полученным параметрам (имя модуля, имя процедуры, количество аргументов, указатель на массив аргументов).Исполняемый модуль (у меня это TestExeModule).
Вот в таком модуле мы объявляем для экспорта процедуруmain, в которую извне будут передаваться
## Код:
```
MODULE TestExeModule;

   IMPORT WinApi, Dynamics;
   
   PROCEDURE ShowMessage (msg, title: ARRAY OF CHAR);
      VAR res: INTEGER;
   BEGIN
      res := WinApi.MessageBoxW(0, msg, title, {});
   END ShowMessage;
   
   PROCEDURE main* (argc: INTEGER; argv: Dynamics.ArgList);
   BEGIN
      ShowMessage("Hello from ExeModule!", "Exe");
   END main;

END TestExeModule.
```

## Код:
```
MODULE Dynamics;

   TYPE
      String* = POINTER TO ARRAY OF CHAR;
      ArgList* = POINTER TO ARRAY OF String;

END Dynamics.
```


## Код:
```
MODULE TestLoader;

   IMPORT WinApi, Dynamics, Loader, StdLog;
   
   PROCEDURE ShowMessage (msg, title: ARRAY OF CHAR);
      VAR res: INTEGER;
   BEGIN
      res := WinApi.MessageBoxW(0, msg, title, {});
   END ShowMessage;
   
   PROCEDURE ReportError (e: Loader.TLoaderError);
   BEGIN
      StdLog.String("===Error #"); StdLog.Int(e.n); StdLog.Ln;
      StdLog.String(e.msg); StdLog.Ln;
      StdLog.String(e.par0); StdLog.Ln;
      StdLog.String(e.par1); StdLog.Ln;
      StdLog.Ln
   END ReportError;
   
   PROCEDURE Run*;
      VAR mod, proc: Dynamics.String;
   BEGIN
      NEW(mod, 64); NEW(proc, 256);
      mod^ := "TestExeModule";
      proc^ := "main";
      Loader.Run(mod, proc, 0, NIL);
      IF Loader.loaderError.n # 0 THEN
         ReportError(Loader.loaderError)
      END;
   END Run;
   
END TestLoader.
```

TestLoader.Run

## Код:
```
MODULE Loader;

   IMPORT WinApi, SYSTEM, Kernel, Meta, Strings, Dynamics, Dialog;
   
   CONST
      modNotFound = 10; procNotFound = 11; identExpected = 12; unknownIdent = 13;
      depositExpected = 14; noDepositExpected = 15; syntaxError = 16;
      lparenExpected = 17; rparenExpected = 18; containerExpected = 19; quoteExpected = 20;
      fileNotFound = 21; noController = 22; noDialog = 23; cannotUnload = 24; commaExpected = 25;
      incompParList = 26;
      
   TYPE
      IntValue = POINTER TO RECORD (Meta.Value)
         int: INTEGER;
      END;
      
      StrValue = POINTER TO RECORD (Meta.Value)
         str: Dialog.String;
      END;
      
      TLoaderError* = POINTER TO RECORD
         n*: INTEGER;
         errorMsg*,
         msg*,
         par0*, par1*: POINTER TO ARRAY OF CHAR
      END;
   
   VAR
      loaderError*: TLoaderError;
      errorMsg: ARRAY 256 OF CHAR;
      par: ARRAY 100 OF POINTER TO Meta.Value;
   
   PROCEDURE ShowMessage (msg, title: ARRAY OF CHAR);
      VAR res: INTEGER;
   BEGIN
      res := WinApi.MessageBoxW(0, msg, title, {});
   END ShowMessage;
   
   PROCEDURE FillChar (VAR s: ARRAY OF CHAR; c: CHAR);
      VAR i: INTEGER;
   BEGIN
      i := 0; WHILE s[i] # 0X DO s[i] := c; INC(i) END;
   END FillChar;
   
   PROCEDURE Init;
   BEGIN
      NEW(loaderError);
      loaderError.n := 0; 
      NEW(loaderError.errorMsg, 256);
      NEW(loaderError.msg, 256);
      NEW(loaderError.par0, 256);
      NEW(loaderError.par1, 256);
   END Init;
   
   PROCEDURE Error (res: INTEGER; msg, par0, par1: ARRAY OF CHAR);
      VAR e, f: ARRAY 256 OF CHAR;
   BEGIN
      IF res # 0 THEN
         loaderError.n := res;
         IF errorMsg # "" THEN
            loaderError.errorMsg^ := errorMsg$
         ELSE
            loaderError.errorMsg^ := "#System:CommandError"
         END;
         loaderError.msg^ := msg$;
         loaderError.par0^ := par0$;
         loaderError.par1^ := par1$;
         (*
         IF errorMsg # "" THEN
            Dialog.MapString(errorMsg, e);
            Dialog.MapParamString(msg, par0, par1, "", f);
            IF e # " " THEN
               f := e$ + ' ' + f$ (*Concat(e, f, f);*)
            ELSE
               Dialog.MapString("#System:CommandError", f)
            END;
            ShowMessage(f, "Error")
         END
         *)
      END
   END Error;
   
   PROCEDURE Run* (_module, _proc: Dynamics.String; argc: INTEGER; argv: Dynamics.ArgList);
      VAR
         res, numPar: INTEGER;
         errmsg: Dialog.String;
   
      PROCEDURE ShowLoaderResult (IN mod: ARRAY OF CHAR);
         VAR res: INTEGER; importing, imported, object: ARRAY 256 OF CHAR;
      BEGIN
         Kernel.GetLoaderResult(res, importing, imported, object);
         CASE res OF
         | Kernel.fileNotFound:
            Error(res, "#System:CodeFileNotFound", imported, "")
         | Kernel.syntaxError:
            Error(res, "#System:CorruptedCodeFileFor", imported, "")
         | Kernel.objNotFound:
            Error(res, "#System:ObjNotFoundImpFrom", imported, importing)
         | Kernel.illegalFPrint:
            Error(res, "#System:ObjInconsImpFrom", imported, importing)
         | Kernel.cyclicImport:
            Error(res, "#System:CyclicImpFrom", imported, importing)
         | Kernel.noMem:
            Error(res, "#System:NotEnoughMemoryFor", imported, "")
         ELSE
            Error(res, "#System:CannotLoadModule", mod, "")
         END
      END ShowLoaderResult;
      
      PROCEDURE CallProc (IN mod, proc: ARRAY OF CHAR);
         VAR i, t: Meta.Item; ok: BOOLEAN;
      BEGIN
         ok := FALSE;
         Meta.Lookup(mod, i);
         IF i.obj = Meta.modObj THEN
            i.Lookup(proc, i);
            IF i.obj = Meta.procObj THEN
               i.GetReturnType(t);
               ok := (t.typ = 0) & (i.NumParam() = numPar);
               IF ok THEN
                  i.ParamCallVal(par, t, ok)
               ELSE
                  Error(incompParList, "#System:IncompatibleParList", mod, proc)
               END
            ELSE
               Error(Kernel.commNotFound, "#System:CommandNotFoundIn", proc, mod)
            END
         ELSE
            ShowLoaderResult(mod)
         END;
         IF ~ok THEN ShowMessage("CallProc error", "Error") END
      END CallProc;
      
      PROCEDURE ParamList ();
         VAR iv: IntValue; sv: StrValue;
      BEGIN
         numPar := 0;
         
         NEW(iv);
         iv.int := argc;
         par[numPar] := iv;
         INC(numPar);
         
         NEW(iv);
         iv.int := SYSTEM.ADR(argv);
         par[numPar] := iv;
         INC(numPar);
      END ParamList;
   
   BEGIN
      Init;
      errmsg := "~";
      ParamList ();
      CallProc(_module, _proc (*"main"*))
   END Run;
   
END Loader.
```


В принципе, частично уже работает: запускается процедура некоторого модуля, у которой нет параметров.
Допустим, если процедура main не имеет параметров и numPar = 0, то всё замечательно запускается. но как только я указываю параметры для передачи аргументов, тут начинаются проблемы.
Судя по всему, проблема заключается в подготовке параметров для передаче их процедуре ParamCallVal.
На строкеi.ParamCallVal(par, t, ok)я получаю ok = FALSE (неудача).

Единственное подозрение у меня вызывает строка
## Код:
```
iv.int := SYSTEM.ADR(argv);
```


Подскажите.