Search code examples
cschemeffiguile

How can I load a foreign library using Guile Scheme?


I want to use a function that I have written in C and compiled into a library using gcc -shared -o libsum.so sum.c, but I don't know how to load the library and call the function from the Scheme interpreter.

I successfully compiled the shared object:

file libsum.so
libsum.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=11ba1cd070663d432026c6494d88d0b5839b58dd, not stripped

from the C source:

int sum(int a, int b) {
  return a + b;
}

and I can see using objdump that my shared object file contains the function I want to use:

00000000000010e9 <sum>:
    10e9:       55                      push   %rbp
    10ea:       48 89 e5                mov    %rsp,%rbp
    10ed:       89 7d fc                mov    %edi,-0x4(%rbp)
    10f0:       89 75 f8                mov    %esi,-0x8(%rbp)
    10f3:       8b 55 fc                mov    -0x4(%rbp),%edx
    10f6:       8b 45 f8                mov    -0x8(%rbp),%eax
    10f9:       01 d0                   add    %edx,%eax
    10fb:       5d                      pop    %rbp
    10fc:       c3                      ret

But when I try to load the file it says that the file doesn't exist:

guile
GNU Guile 3.0.9
Copyright (C) 1995-2023 Free Software Foundation, Inc.

Guile comes with ABSOLUTELY NO WARRANTY; for details type `,show w'.
This program is free software, and you are welcome to redistribute it
under certain conditions; type `,show c' for details.

Enter `,help' for help.
scheme@(guile-user)> (use-modules (system foreign)
                                  (system foreign-library))
scheme@(guile-user)> (load-extension "libsum" "sum_init")
ice-9/boot-9.scm:1685:16: In procedure raise-exception:
In procedure dlopen: file "libsum.so", message "libsum.so: cannot open shared object file: No such file or directory"

Entering a new prompt.  Type `,bt' for a backtrace or `,q' to continue.
scheme@(guile-user) [1]>

The file "libsum.so" is in the current working directory, so I don't know what could be going on.

Any help would be appreciated!


Solution

  • load-extension uses load-foreign-library to load shared libraries, which in turn looks in a list of directories for a plain name:

    Unless library denotes an absolute file name or otherwise contains a directory separator (/, and also \ on Windows), Guile will search for the library in the directories listed in search-paths.

    Your current working directory probably isn't in that search path. Try adding a directory separator as suggested by the documentation to explicitly use the CWD:

    (load-extension "./libsum" "sum_init")