I apologize in advance for the length of this post.

I'm trying to build a gateway that allows CL to communicate with R (a
statistical package).  R has a C API for embedding it, which I want to
use.  I have an example python module (rpy) that does this, and I've
also written an eight-line C program which starts up an embedded R.
So far, my attempts to translate this to CL have not been successful.

I started with UFFI, but I've decided to work first directly at the
CMUCL level, and try to achieve portability later.  At this point, I'm
guessing my primary difficulty is a lack of understanding of what's
necessary with shared libraries.

When I link my eight line C program, I have to link with a shared
library libR.so ("-lR" in the call to gcc).  Doing an ldd on libR.so,
I see that it depends on a number of other libraries:

[EMAIL PROTECTED] rif]$ ldd /usr/local/lib/R/bin/libR.so
        libblas.so.3 => /usr/lib/libblas.so.3 (0x00cf0000)
        libg2c.so.0 => /usr/lib/libg2c.so.0 (0x00c48000)
        libm.so.6 => /lib/tls/libm.so.6 (0x00111000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00f82000)
        libreadline.so.4 => /usr/lib/libreadline.so.4 (0x00f36000)
        libdl.so.2 => /lib/libdl.so.2 (0x003eb000)
        libncurses.so.5 => /usr/lib/libncurses.so.5 (0x00bc5000)
        libc.so.6 => /lib/tls/libc.so.6 (0x00ded000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x007dc000)
        libgpm.so.1 => /usr/lib/libgpm.so.1 (0x00522000)

>From the alien:load-foreign documentation, I see that load-foreign has
a :libraries keyword: "libraries is a list of simple-strings
specifying libraries in a format that ld, the Unix linker, expect."
Although the docs don't actually say what these strings are used for,
I'll choose to not be a rules-lawyer, and assume that this is supposed
to be a list of libraries that the foreign object file depends on.

Currently, I am using the following to load the R library:

  (alien:load-foreign "/usr/local/lib/R/bin/libR.so"
                      :libraries '("-lc" "-lgpm" "-lncurses" "-ldl" 
                                   "-lreadline" "-lm" "-lblas"))

I removed "-lgcc_s" and "-lg2c" from an earlier version of the call
because their inclusion caused ld to fail, even though they are in the
same directories (/lib and /usr/lib) as other libraries that were
found --- I do not know why.  I did not include /lib/ld-linux.so.2 at
all, as I'm not sure what the "link option" for this is.  Any comments
on these choices are welcomed.

Question: Can I just load the library I want to call, or do I need to
climb up the tree of dependencies, calling load-foreign on each one
independently?

The function itself is declared as:

(alien:def-alien-routine ("Rf_initEmbeddedR" start-r)
  integer
  (argc integer :in)
  (argv (* foreign-string) :in))

In any case, the upshot is that as of now, I have an eight-line C
program that can start an embedded R, but all attempts to do it from
CMUCL lead to an "Arithmetic error FLOATING-POINT-INVALID-OPERATION
signalled" inside the call, beneath about six "Foreign function call
land" stack frames, which I don't know of any way to directly debug.
(This is assuming I set the environment variable R_HOME appropriately,
which I do using the :osicat package.  If I fail to do this, then
calling my function to start up R simply causes CL to crash.)

As a side piece of information, I wrote a tiny C program that contains
a single function with the same signature as Rf_initEmbeddedR (int
argc, char **argv) that returns the sum of the lengths of the strings
given as arguments.  Doing a def-alien-routine with the same signature
as above, and in both cases (of course) converting an array of CL
strings into an aray of (* (alien:unsigned 8)), the little C program
works fine, so I'm guessing that I have the calling conventions and
the string handling OK, making me suspect some shared library problem.

Any help or advice is appreciated.

Cheers,

rif


Reply via email to