by mail.SOL42.com with ESMTPA id 4e70f9360481a1;

        Wed, 14 Sep 2011 20:57:58 +0200

Content-Type: text/plain; charset=iso-8859-1

Mime-Version: 1.0 (Apple Message framework v1084)

Subject: Re: [Caml-list] Link a .so/.dll dynamically

From: [email protected]

In-Reply-To: <1316016912.24759.29.camel@aurora>

Date: Wed, 14 Sep 2011 20:57:58 +0200

Content-Transfer-Encoding: quoted-printable

Message-Id: <[email protected]>

References: <[email protected]> <1316016912.24759.29.camel@aurora>

To: [email protected]

X-Mailer: Apple Mail (2.1084)



On 14 Sep 2011, at 18:15, J=E9r=E9mie Dimino wrote:

> You can also use dlopen and dlsym on unix, and=20

> LoadLibrary and GetProcAddress on windows.



Right.  For truly dynamic loading, if you already have a set of .so =

files with similar API you might want to write some "loader" in C and =

compile that into your OCaml program.  No need to put an extra dynlink =

layer in between.  BTW Dynlink is not available on all platforms.



In this "loader" you would call dlopen() and dlsym() (or their Windows =

counterparts) to get the addresses of the functions in the .so, and make =

them available to the rest of your OCaml program.  You still need to =

translate OCAml-to-C function arguments and C-to-OCaml function results. =

 Note that this is somewhat insecure C plumbing, you can easily bring =

down the whole process in a number of ways.





While it is way too soon for announcements, I do have some very =

experimental code that allows to do exactly this in pure OCaml.  All you =

need to do is write a C wrapper, sort of like how you do it in Python =

(see http://docs.python.org/extending/extending.html for example).  The =

OCaml code looks like this:



# #load "dffi.cma";;

# open DL;;

# #install_printer Pointer.pp;;



# let lib =3D dlopen "/wherever/pgtest.dylib" [];;

val lib : DL.dllib =3D <abstr>



# let connect          =3D dlsym lib "pq_connect_db" and

    disconnect       =3D dlsym lib "pq_finish" and

    protocol_version =3D dlsym lib "pq_protocol_version";;

val connect : DL.dlfun =3D <abstr>

val disconnect : DL.dlfun =3D <abstr>

val protocol_version : DL.dlfun =3D <abstr>



# let [|conn|] =3D dlcall connect [|String "dbname=3Dname_of_database"|];;=



val conn : DL.cval =3D Ptr (PGconn*)0x0000000100100ef0



# dlcall protocol_version [|conn|];;

- : DL.cval array =3D [|Int 3|]



# dlcall disconnect [|conn|];;

- : DL.cval array =3D [||]



# dlclose lib;;

- : unit =3D ()



And pgtest.c (a PostgreSQL client lib protowrapper) looks like this:



#include <sys/types.h>

#include <unistd.h>

#include <errno.h>

#include <stdio.h>

#include <libpq-fe.h>



#include "dlutil.h"



FUNC(pq_connect_db) {

        ARGS; DECL;

        PGconn* conn;

        CHECKNUMARGS(1); CHECKSTR(0); /*1 arg, must be String*/

        conn =3D PQconnectdb((const char*)GETSTR(0));

        if (PQstatus(conn) =3D=3D CONNECTION_OK) {

                ALLOC(1); /*return 1 value*/

                SETPTR(0, PGconn*, conn); }

        else {

                PQfinish(conn);

                ALLOC(0); }

        RETURN; }



FUNC(pq_finish) {

        ARGS; DECL;

        CHECKNUMARGS(1); CHECKPTR(0); CHECKPTR_TYPE(0, PGconn*);

        PQfinish(GETPTR(0, PGconn*));

        ALLOC(0);

        RETURN; }



FUNC(pq_protocol_version) {

        ARGS; DECL;

        CHECKNUMARGS(1); CHECKPTR(0); CHECKPTR_TYPE(0, PGconn*);

        ALLOC(1);

        SETINT(0, PQprotocolVersion(GETPTR(0, const PGconn*)));

        RETURN; }



FUNC, ARGS, CHECKNUMARGS and the rest are nasty dlutil.h macros that do =

all the OCaml-C magic as described in the OCaml docs.



Functions all have the same signature, they receive an array of values =

amd can check the number and type of its elements.  They return another =

array, like multiple value returns in Lisp.  You can get pretty creative =

with this scheme.



This is very early code with plenty of missing stuff, and I haven't used =

it for anything serious yet, but if it might be of use to anyone as-is =

then just ask.





Regards.

-Daniel




-- 
Caml-list mailing list.  Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Reply via email to