Subject: [clisp-list] ffi:foreign-library doesn't find library

From: Michael Goffioul <[email-masked]>
Date: Wed May 26 01:52:22 2004

Hi, 
 
I defined a set of foreign functions located in a shared library. The problem 
is that this library is not located in a standard place. So I looked at the 
code and found that (under UNIX) ffi:foreign-library uses "dlopen" such that I 
should be able to solve the problem by changing LD_LIBRARY_PATH variable. 
 
So I used somthing like: 
 
(system::setenv "LD_LIBRARY_PATH" 
  (string-concat "./lib:" (ext::getenv "LD_LIBRARY_PATH"))) 
 
(ffi:def-call-out myfun (:library "libmyfun.so") ...) 
 
which change the environment variable before defining my foreign function. 
However, it doesn't change anything and foreign-library still complains it 
cannot find my library. If I change the variable before starting clisp (and 
remove the "setenv" LISP call), it works fine. Is this normal? 
 
Note: I'm using clisp-2.33 (RPM compiled for RH9, used under Mandrake-9.2) 
 
Thanks. 
Michael.

---

From: Michael Goffioul <[email-masked]>
Date: Wed May 26 02:13:23 2004

Michael Goffioul <michael.goffioul <at> imec.be> writes: 
[snip] 
> remove the "setenv" LISP call), it works fine. Is this normal?  
 
Forget it. It looks like this is how LINUX works. I tried something 
similar in plain C, and got the same error. 
 
Michael.

---

From: "John K. Hinsdale" <[email-masked]>
Date: Wed May 26 06:14:23 2004

> From: Michael Goffioul <[email-masked]>

 > shared library. ... is not located in a standard place.  under
 > UNIX) ffi:foreign-library uses "dlopen" ... I should be able to
 > solve the problem by changing LD_LIBRARY_PATH variable.

 > So I used somthing like: (system::setenv "LD_LIBRARY_PATH" (string-concat "./lib:" (ext::getenv "LD_LIBRARY_PATH"))) 

Yes, this is how the Linux dynamic loader works.  It examines the
value of $LD_LIBRARY_PATH at process startup time, and the search path
seen by the loader is "frozen" for the duration of the process -- you
can't modify its search path during the program by changing
$LD_LIBRARY_PATH with putenv().

As you saw, changing the variable before starting CLISP will cause the
CLISP process to see your desired path at process startup time and
that is why it works.

 > Note: I'm using clisp-2.33 (RPM compiled for RH9, used under

It's not dependent on CLISP verson; it's a Linux/Unix thing.

There are two basic workarounds for this situation:

  - Wrap the CLISP program in a shell script that sets
    LD_LIBRARY_PATH and then call CLISP from that script

	#!/bin/sh
	LD_LIBRARY_PATH=/my/special/libdir:${LD_LIBRARY_PATH}
	export LD_LIBRARY_PATH
	clisp ....

  - You can take advantage of the fact that dlopen() allows
    absolute or relative paths to be part of the library
    name argument.  In this case you would construct in Lisp
    the path name to the library file so as to include to your
    nonstandard directory:

       (setf my-lib "/my/special/libdir")
       (ffi:def-call-out myfun
          (:library (string-concat my-lib "/" "libmyfun.so") ...) 

Neither of these is particulary elegant but they do work.

I'm not sure why the Linux/Unix designers have the shared library
loader "freeze" the load path at start time, whether that is
considered a good thing or if it was hard to implement otherwise.

[Years ago I had to deal w/ OS/2 where the library path (DLLPath) was
set and frozen systemwide at BOOTUP!!]

---
John Hinsdale, Alma Mater Software, Inc., Tarrytown, NY 10591-3710 USA
[email-masked] | http://www.alma.com/staff/hin | +1 914 631 4690

---

From: Sam Steingold <[email-masked]>
Date: Wed May 26 06:37:15 2004

> * Michael Goffioul <[email-masked]> [2004-05-26 08:37:06 +0000]:
>

please do not use functions in SYS.
<http://clisp.cons.org/impnotes/getenv.html>.

-- 
Sam Steingold (http://www.podval.org/~sds) running w2k
<http://www.camera.org> <http://www.iris.org.il> <http://www.memri.org/>
<http://www.mideasttruth.com/> <http://www.honestreporting.com>
Garbage In, Gospel Out