Pliant talk forum

Pliant talk forum

Discussion: Pliant-Perl Binding

I posted the code on SourceForge.
Message posted by maybe Boris Reitman on 2003/12/10 06:52:50
I have setup a project on SourceForge,

The modulename to checkout is 'pliant-perl'.
The way to use the checkout is to symlink /pliant/pliantx  
into  /where_you_checkout/pliant-perl/pliantx

The two major things left to do is,

- to remove the wrapper library and talk directly 
  with the system perl library. 
- figure out how to pass a Pliant callback to Perl, with minimum amount of work
  for programmer, something like,

  function visit_string str
    arg Str string
    console string eol

  perl_eval {{  sub hello { my $sub = shift; &$sub("hello") } }}
  perl "hello" visit_string

The visit_string function must be dynamically wrapped in a 
function X. This function X will fetch the arguments from the perl runtime 
stack and feed it into visit_string.  X will be implemented depending
on the input arguments of visit_string.  I will use Y in place of visit_string.

  function Y  int str perlarray
    arg Int int
    arg Str str
    arg PerlArray perlarray

  Then X will pop two PerlScalar arguments from the perl stack,
  convert the first to Int, the second to String, and the rest of the
  arguments will be popped and placed into a PerlArray object.
  Then X will call Y with the three arguments, namely, integer, string, 
  and the PerlArray object.
Message posted by maybe Boris Reitman on 2003/12/17 19:33:51
The binding now allows to access relational databases and execute
SQL through Perl's DBI layer.  This means that big database applications
can be written in Pliant.  The Perl DBI framework supports a very wide range
of databases.


module "/pliant/language/compiler.pli"
module "/pliantx/language/perl.pli"
module "/pliantx/lexer/multiline_string.pli"

perl_eval {{ use DBI; }} 

gvar PerlScalar dbh
gvar Str data_source := "dbi:Pg:dbname=test_db";
gvar Str data_username := "";
gvar Str data_password := "";
dbh := perl "DBI::connect" "DBI" data_source data_username data_password

gvar PerlScalar ref_records
ref_records := perl dbh "selectall_arrayref" "select * from products;"

gvar PerlArray records := ref_records array
gvar PerlArray record

for (gvar Int i) 0 records:size-1
  console "Record " i eol
  record := records:i:array
  for (gvar Int j) 0 record:size-1
    console j ": "  (cast record:j Str) eol
perl dbh "disconnect"



Record 0
0: A1
1: Apple
Record 1
0: A2
1: Orange
Record 2
0: A3
1: Banana
Record 3
0: A4
1: Peach

Message posted by hubert.tonneau on 2003/12/17 20:28:48
What is your opinion about the advantages and limits of a through Perl database
binding, rather than a direct binding of let's say MySQL though it's C client
library ?
Message posted by maybe Boris Reitman on 2003/12/17 22:49:54
- Perl module must be dynamically loaded
- Perl is slow compared to Pliant
- Data arrives inside Perl data structure
  Because Perl is slower than Pliant it will
  be more expensive to manipulate the data in the 
  perl structures.  It will also be expensive
  to copy it into pliant structure (overhead of copying).

- DBI supports many databases through the DBI/DBD
  (DBI -- Database Interface, DBD -- Database Driver)
  framework.  The interface is the same for all databases.
- The time the database takes to produce the SQL will 
  probably contribute a significantly longer delay
  than the delay introduced by the perl bridge.
- We can implement a more efficient (directly through C) 
  interfaces later, so that we follow the rule
  "make it work first, then make it better".  

I think we should wrap the DBI gateway in an all Pliant
interface so that if we make a direct implementation 
for some of the more popular databases, the end-user 
code doesn't need to be changed.

I would like to have a library like Tangram (Perl) or
Castor (Java) to be implemented in Pliant, so that objects can be
transparently saved and restored in relational database given 
some schema.

Message posted by hubert.tonneau on 2003/12/18 10:29:47
> I think we should wrap the DBI gateway in an all Pliant
> interface so that if we make a direct implementation 
> for some of the more popular databases, the end-user 
> code doesn't need to be changed.

This needs to be done in the Pliant database engine itself,
since /pliant/appli/database/prototype.pli
is definining an API, not an implementation.

The default implementation (XML like files) is in /pliant/appli/database/file.pli (*)

Also, if the implementation is RPC to an SQL server, then the
each xxx xxx filter xxx sort xxx
should be optimised to a single select query.

(*) Please notice that the current implementation is very very subtimised:
for each access we do, we lock the database, create a new database pointer,
then unlock.
A way to speed up an order of magnitude the database engine is to recognise
some conforming blocs, and move all database operations in the bloc to:
test if the database implementation is the expected one
if yes
  lock the database
  execute the optimised bloc where all database operations apply transparently
  on datas, so that we get raw C speed
if no
  use default non optimised code
Message posted by reitman on 2004/05/28 21:37:46
FYI, I have been able to interface through wxPerl into wxWindows.
This means it is now possible to write GUIs with pliant.
I will be working on improving things in the following few weeks.

Message posted by maybe Cetin on 2005/04/06 14:03:41

I am using Perl V5.8.0 on AIX 5L with Oracle 9i. I am living some problems with DBI. Since I am not familiar with Perl too much I am not able to understand if DBI is installed or not. Can anyone helps me to learn if DBI is installed or not, if it is installed how to learn its version and if it is not how to install DBI and which version shoul be installed. 

Message posted by maybe Boris Reitman on 2005/04/06 15:18:46
If the following fails then you don't have DBI working.

use DBI;
$data_source = "fill-in";
$username = "fill-in";
$auth = "fill-in"
$dbh = DBI->connect($data_source, $username, $auth);

consult the DBI pod documentation:

$ perldoc DBI
$ man DBI

PS. I think this should go to the newbie questions forum...
Message posted by maybe Boris Reitman on 2006/01/15 10:30:35
The pliant-perl binding now works on windows.

It also comes with tests using Test::Harness adapted to Pliant.
Message posted by maybe Boris Reitman on 2006/01/18 06:33:16
made another release that fixed a bug.
Message posted by maybe Boris Reitman on 2006/05/24 07:02:33
Is it possible to run pliant as a .SO rather than executable ? 
This would allow me to create an Inline::Pliant module for Perl, so that 
perl programmers can start putting pieces of pliant code inside their perl code,
for optimization purposes.

I realize that we want to put everything inside Pliant, but giving a way to perl
programmers to use pliant will create more pliant users and eventually many will
change from embedding of pliant inside perl to embedding of perl inside pliant. 
Then, people will learn enough pliant to write programms exclusively in it.
This way we don't need to explain advanced concpets of 
pliant to win many users.  The users will discover that by themselves once they 
start using it. There are millions of perl users out there, and embedding pliant 
inside perl will allow them to start programming in a strong programming language.
There is already Inline::C and Inline::CPP module, but programming in C++ is a 
pain, so people will prefer pliant. Right now only perl experts move critical 
perl code into C or C++ space. Having pliant inside perl will allow much more 
people to create better code.

The other side effect is that packaging of pliant will improve.

So to repeat, what would it take to allow pliant as a .SO ? I undrestand that on windows we already have .DLL.

Message posted by hubert.tonneau on 2006/05/24 09:00:36
Just run:
/pliant/pliant/install/make-linux-i386-gcc dll

then read:
and maybe
to discover how to start the Pliant engine from another program.
Message posted by maybe Boris Reitman on 2006/05/24 19:08:24
There a problem with using -fPIC and /pliant/pliant/os/linux_kernel.c

This compiles ok, it's the line from 
gcc-2.95 -I/pliant/pliant/language/startup -O2 -m486 -mregparm=3 -mrtd -D_REGISTERS_ -D_NOCHECK_ -fomit-frame-pointer -D_LISTING_ -Dc_debugging_level=1 -s -nostdlib -ldl -D_SO2_ /pliant/pliant/language/startup/start.s -D_i386_ -D_LINUX_API_ -D_LINUX_ -D_GCC_ /pliant/pliant/language/startup/loader.c

Adding option -fPIC does this:

gcc-2.95 -fPIC -I/pliant/pliant/language/startup -O2 -m486 -mregparm=3 -mrtd -D_REGISTERS_ -D_NOCHECK_ -fomit-frame-pointer -D_LISTING_ -Dc_debugging_level=1 -s -nostdlib -ldl -D_SO2_ /pliant/pliant/language/startup/start.s -D_i386_ -D_LINUX_API_ -D_LINUX_ -D_GCC_ /pliant/pliant/language/startup/loader.c

Gives this compile error:
/pliant/pliant/language/startup/loader.c: In function `startup':
/pliant/pliant/language/startup/loader.c:44: Invalid `asm' statement:
/pliant/pliant/language/startup/loader.c:44: fixed or forbidden register 3 (bx) was spilled for class BREG.
/pliant/pliant/language/startup/loader.c:44: Invalid `asm' statement:
/pliant/pliant/language/startup/loader.c:44: fixed or forbidden register 3 (bx) was spilled for class BREG.

The -fPIC option is needed in order to dynamically load a .so module into perl.

There is account for this error message on google, and they say something wrong
is with the asm code: that the ebx register is a reserved one.
Message posted by hubert.tonneau on 2006/05/24 19:58:34
> The -fPIC option is needed in order to dynamically load a .so module into perl.

I will not help you much in this area because first I have no serious
documentation about GCC, second Perl seems to be full of dirty tricks, and third
Pliant is also dirty because of the dump file restore that has to be done without
the help of the operating system.

So, in very fiew words, if when Pliant is started another time the Pliant DLL
is loaded at a different address, then Pliant will not be abble to reload it's
dump file.
If external DLLs used by Pliant through Pliant 'external' instruction load at
a different address, then it should ok because Pliant keeps track of each call
to an external function. On the other hand, Pliant does not keep track of the
calls to it's C part, so if the Pliant DLL loads at a different address, then
the dump file is unusable.

It reminds me why I stopped building Pliant as a DLL under Linux.
If Pliant is compiled as a DLL, then each time you upgrade your packages,
so upgrade the law level DLLs, then Pliant DLL load address changes, and as
a result all dumps files need to be rebuilt.

Message posted by maybe Boris Reitman on 2006/05/24 21:15:06
>So, in very fiew words, if when Pliant is started another time the Pliant DLL
>is loaded at a different address, then Pliant will not be abble to reload it's
>dump file.

How is this different from the case when pliant is started as executable ?
Are you saying that when pliant is started as an executable,
pliant is getting the full block of memory with a virtual address of 0,
while when it is loaded as a DLL, virtual address of 0 is in use by the perl 
process that is already running, and therefore the DLL will be loaded at some 
internal address inside the memory block of that process ?

pliant an executable: 

  [pliant compiler part .... (dump files loaded here)]
   0 1 2 3 4 ............... 100

pliant as dll loaded by perl:

  [perl ..... (pliant dll  .... (dump files loaded here))]
   0 1 2 3... 157...............257......................]
  <--- memory block for the process --------------------->

Do I understand correctly ? And, it would be difficult to adjust the dump files
to respect the introduced offset ?
Message posted by hubert.tonneau on 2006/05/24 21:40:47
As far I as understand it, an executable is always loaded at fixed address.

So, an executable is the same as a library forced to load at fixed address.
On Linux I use an executabe,
under Windows, I use a library forced to load at fixed address.

DLL or executable is not the important; the important is fixed address.

The difficulty is that forcing DLLs to load at fixed address is not easy
because it's basically bad practice (there is only one executable in the
process, but they can be many DLLs) so development tools are all designed
to build relocatable DLLs.
Message posted by maybe Boris Reitman on 2006/05/25 00:37:27
In this case I am postponing this work until pliant 
handling of dump files improves, so that pliant dll is possible on linux. 
I don't see another workaround.
Message posted by hubert.tonneau on 2006/05/25 10:13:13
> until pliant handling of dump files improves

It can hardly improve as long as we have a C part.
So, it basically turns to: the problem will resonably properly be solved only
if we have a Pliant cross compiler (see FIG project) so that the C part is
just a dump loader.

On the tricks side, I'm not that sure Perl cannot read a DLL that loads at
a fixed address. The explaination might be that it cannot because the
area of memory requested by the DLL has already been assigned, so that
it might work if a different loading address is requested.
This can probably be adjusted though '--image-base' option of the linker
(see /piant/install/make-win32-i386-gcc)
Now, you probably have to dig deaply in Linux documentation about /proc
and others to disover where the kernel provides the list of memory areas
assigned by a running process.