Recent

Author Topic: Calling procedure of library via a script ?  (Read 19301 times)

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Calling procedure of library via a script ?
« Reply #15 on: July 15, 2014, 05:04:13 pm »
Hum, maybe that way ( how to ? ).... ?

Code: [Select]
library mylib;
type
  TMyLibAPI = record
     version : Integer;
     proc1 : procedure(x, y, z : integer); 
     proc2 : procedure (x : string); 
     proc3 : procedure (x : boolean); 
  end;

procedure proc1(a,b)
begin
..
end;

procedure proc2(a,b)
begin
..
end;

procedure proc3(a,b)
begin
..
end;

procedure GetMyLIPAPI( var apirec: TMyLibAPI )
begin
  apirec.version = VERSION_OF_MYLIB;
  apirec.proc1:=@proc1;
  apirec.proc2:=@proc2;
  apirec.proc3:=@proc3;
end;

Code: [Select]
program main;
type
TMyLibAPI = record
     version : Integer;
     proc1 : procedure(x, y, z : integer); 
     proc2 : procedure (x : string); 
     proc3 : procedure (x : boolean); 
  end;

procedure GetMyLIPAPI( var apirec: TMyLibAPI ); external;

var
  api : TMyLibAPI;
begin
  GetMyLIPAPI(api);
  api.proc1(1,2,3);
  api.proc2('blah', 'blah');
  api.proc3(x);

Something similar is used in C-style libraries. For example zlib, uses this approach to interface dataread and memory routines.

Eventually (for better cross-language and cross-process compatibility) the idea of passing records evolved to (com/corba) Interfaces. From the low level point of view, they are still same records with function references.

« Last Edit: July 15, 2014, 05:08:14 pm by skalogryz »

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #16 on: July 15, 2014, 05:11:34 pm »
@ skalogryz =>  :-* XXL.

I will study your code and try it.

Write you later....

Many thanks.

Fred
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Calling procedure of library via a script ?
« Reply #17 on: July 15, 2014, 05:16:28 pm »
I will study your code and try it.
You need to research if this approach is friendly to high-level scripting languages such as Python, Java and (Visual?) Basic.

Once the research is done, ask yourself: what's the benefit of this approach over a regular library export.

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #18 on: July 15, 2014, 06:18:41 pm »
Ok, im back...

Nice code but... this one =>

Code: [Select]
program main;
type
TMyLibAPI = record
     version : Integer;
     proc1 : procedure(x, y, z : integer); 
     proc2 : procedure (x : string); 
     proc3 : procedure (x : boolean); 
  end;

With my (little) experience of library, i note that, to avoid problems, you have to ask the less possible to the program who will use the library.

The only easy-accessible variables for each languages are:

- Integers.
- Float.
- Strings (but not so easy).

And, it is really difficult to deal with:

- Classes.
- Procedures.

The only universal way i see is to use strings as command...
Like this one :
Code: [Select]
program main;
var
thecom : string;
begin
thecom := 'proc1(1,2,3)';
run_lib_command(thecom);
end;

But it seems that is not possible with fpc directly...

I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Calling procedure of library via a script ?
« Reply #19 on: July 15, 2014, 06:32:51 pm »
- Strings (but not so easy).
That's possible the hardest type to be passed for different languages.
As each language implements them in various ways (multiple times)

Need to mention, that Microsoft has achieved some good solution here with COM interfaces and OLE Strings (WideStrings on Pascal, but not UnicodeStrings).
OleStrings works flawlessly (from my experience) throughout all languages that support COM Interfaces on Windows

- Procedures
- Classes
Both are the easiest!
Procedures come naturally (as long as a language has an understanding of a routine/function, in the same manner as C-does.)
Classes are typically replaced with opaque "Pointer" or pointer-sized integer. With proper methods exposed and functions.
« Last Edit: July 15, 2014, 06:37:08 pm by skalogryz »

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #20 on: July 15, 2014, 06:40:05 pm »
Quote
That's possible the hardest type to be passed for different languages.
As each language implements them in various ways (multiple times)

Yep, maybe, but i have easy solutions for C, Python, Pascal, Java and Basic.

With classes and procedures (method) => difficult with Java and Basic.

And, using Com interface will give problems with some OS...

But nice to open and clarify the way...

Thanks
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Calling procedure of library via a script ?
« Reply #21 on: July 15, 2014, 06:44:37 pm »
Quote
That's possible the hardest type to be passed for different languages.
As each language implements them in various ways (multiple times)

Yep, maybe, but i have easy solutions for C, Python, Pascal, Java and Basic.

But isn't a Java string  a class?
 

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #22 on: July 15, 2014, 06:53:41 pm »
Quote
But isn't a Java string  a class?

Hum, i only try Java by testing my "universal" fpc libraries...
So, i do not know...
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #23 on: July 15, 2014, 07:26:33 pm »
Hello.

Other way...

Does it exist a equivalent of TProcess for Internal process ?

=> TProcess :

Quote
...
var
VProcess: TProcess;
begin
VProcess.CommandLine := 'gdb';
VProcess.Execute;

=> TInternalProcess :

Quote
...
var
VProcess: TInternalProcess;
begin
VProcess.CommandLine := 'proc1(1,2,3)';
VProcess.Execute;

?

« Last Edit: July 15, 2014, 07:38:09 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Calling procedure of library via a script ?
« Reply #24 on: July 15, 2014, 08:04:24 pm »
Well of course! TInternalProcess! how could I forgot about that!
Great catch, Fred !

here's an example!

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: Calling procedure of library via a script ?
« Reply #25 on: July 15, 2014, 09:17:05 pm »
=> TProcess :

Quote
...
var
VProcess: TProcess;
begin
VProcess.CommandLine := 'gdb';
VProcess.Execute;

Searches on disc already compiled program, if found starts already compiled program "gdb"
Quote
=> TInternalProcess :

Quote
...
var
VProcess: TInternalProcess;
begin
VProcess.CommandLine := 'proc1(1,2,3)';
VProcess.Execute;

?

No. Since that would require a compiler, and that was already answered in the first question. EXECUTING CODE IN STRINGS IS NOT POSSIBLE UNLESS YOU PULL IT THROUGH AN (EXTERNAL) COMPILER. The only escape is using scripting languages, but that is a entirely different matter. In general performance and control suffers that way.

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #26 on: July 16, 2014, 12:07:00 am »
Quote
here's an example!

Hum, it seams exactly what i want...   :o

So i do not understand... =>
Quote
EXECUTING CODE IN STRINGS IS NOT POSSIBLE UNLESS YOU PULL IT THROUGH AN (EXTERNAL) COMPILER.

I have to re-study skalogryz-code... (if it is not a joke-code then it is a bomb-code...).

I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #27 on: July 16, 2014, 12:28:00 am »
Yep, nice code skalogryz  ;)

The only part i do not like too much is this one =>
Code: [Select]
procedure HiddenProc(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
begin
  Proc1(args[0].ResInteger, args[1].ResInteger, args[2].ResInteger);
  Result.ResInteger:=0;
end;

initialization
  RegisterProc('proc1', 'III', @HiddenProc);

But, yes, very, very promising way...

Write you later...
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3158
    • StrumPract is the musicians best friend
Re: Calling procedure of library via a script ?
« Reply #28 on: July 16, 2014, 01:22:57 am »
Hum, it seams that skalogryz-code is not a joke, so be careful, it could be a bomb...

Look at that :

The program =>
Code: [Select]
program project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes,
   libunit; // the pseudo-library

begin
 ProcExported('Proc1(1,2,3)');
end.

The pseudo-library =>
Code: [Select]
unit libunit;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, internalprocess;

procedure Proc1(a,b,c: Integer);

procedure ProcExported(theproc: string);  /// Exported in library

implementation

procedure Proc1(a,b,c: Integer); /// not exported in library
begin
  writeln(a);
  writeln(b);
  writeln(c);
end;

procedure ProcExported(theproc: string); /// Exported in library
var
  VProcess: TInternalProcess;
begin
  VProcess:= TInternalProcess.Create;
  try
    VProcess.CommandLine := theproc;
    VProcess.Execute;
  finally
    VProcess.Free;
  end;
end;

procedure HiddenProc(Var Result : TFPExpressionResult; Const Args : TExprParameterArray);
begin
  Proc1(args[0].ResInteger, args[1].ResInteger, args[2].ResInteger);
  Result.ResInteger:=0;
end;

initialization
  RegisterProc('proc1', 'III', @HiddenProc);
end.

And the bomb =>
Code: [Select]
unit internalprocess;

{$mode delphi}{$H+}

interface

uses
  Classes, SysUtils, fpexprpars;

Type
  TFPExpressionResult = fpexprpars.TFPExpressionResult;
  TExprParameterArray = fpexprpars.TExprParameterArray;
  TFPExprFunctionCallBack = fpexprpars.TFPExprFunctionCallBack;

  { TInternalProcess }

  TInternalProcess = class(TObject)
  private
    fCommandLine : string;
  public
    LastError : string;
    procedure Execute;
    property CommandLine: string read fCommandLine write fCommandLine;
  end;

procedure RegisterProc(const name, types: string; ptr: TFPExprFunctionCallBack);

implementation

var
  IntProc : TStringList;

procedure RegisterProc(const name, types: string; ptr: TFPExprFunctionCallBack);
begin
  IntProc.AddObject(name+'|'+types, TObject(@ptr));
end;

{ TInternalProcess }

procedure TInternalProcess.Execute;
var
  exp : TFPExpressionParser;
  i   : Integer;
  nm  : string;
  j   : Integer;
  ptr : TFPExprFunctionCallBack;
begin
  try
    exp:=TFPExpressionParser.Create(nil);
    try
      for i:=0 to IntProc.Count-1 do begin
        ptr:=TFPExprFunctionCallBack(IntProc.Objects[i]);
        nm:=IntProc[i];
        j:=Pos('|',nm);
        exp.Identifiers.AddFunction(Copy(nm, 1, j-1), 'I', Copy(nm, j+1, length(nm)), ptr);
      end;
      exp.Expression:=fCommandLine;
      exp.Evaluate;
    finally
      exp.Free;
    end;
  except
    on E: Exception do
      LastError := E.Message;
  end;
end;

initialization
  IntProc := TStringList.Create;

finalization
  IntProc.Free;

end.
 

With that code, i get exactly what i want ( but, yes, some "hidden" code to add to original code...).

=> @ Marcov and Skalogryz : ok, you win, where is the bug (if there is one) ?
« Last Edit: July 16, 2014, 01:32:07 am by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

skalogryz

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 2770
    • havefunsoft.com
Re: Calling procedure of library via a script ?
« Reply #29 on: July 16, 2014, 02:37:29 am »
=> @ Marcov and Skalogryz : ok, you win, where is the bug (if there is one) ?
There's no bug. You need to understand and accept the following:
* pascal has no built-in features for "compiling" in run-time, because it's a compiled language. Most of programs written with pascal doesn't need the feature... except for the compiler itself.
* in order to be able to "compile" a code in run-time you'll need the proper code -> either use a pascal compiler code or a interpretting (scripting) code.
* either solution will come with it's own price: size - your library will grow, performance - executing a script in run-time always comes with a (small) penalty.
You also need to make sure that this "compile" time won't affect your library. Multimedia code is typically time critical.

That's it. if you really need scripting - you must accept to pay the price.
Or on the other hand, just expose the address of functions (by either exporting them as library functions / procedural variables in a records / interfaces). In that case, there's no price, but some (none?) issues for other languages. And yes, it might require you to do some extra wrappers for your internal library structure.

The choise is yours, and you can take either approach and just see how either works.
The price of "size" and "time" will depend on the choice of a "scripting" implementation you choose.

----
...oh, and feel free to post P-code request with LGPL license to the bugtracker :) and yes - send patches

 

TinyPortal © 2005-2018