Errors in reloading foreign c++ libraries

Hi,
While reloading foreign c libraries works well I run into issues while reloading foreign c++ libraries.

---------------------- a simple cpp file ---------------------------
// hello.cpp

#include <SWI-cpp.h>
#include <iostream>

PREDICATE(hello, 0) {
  std::cout << "Hello!" << std::endl;
  return TRUE;
}

--------------------------- compiling and linking ----------------
Arthurs-MacBook-Pro:foreign laowang$ uname -a
Darwin Arthurs-MacBook-Pro.local 18.2.0 Darwin Kernel Version 18.2.0: Thu Dec 20 20:46:53 PST 2018; root:xnu-4903.241.1~1/RELEASE_X86_64 x86_64
Arthurs-MacBook-Pro:foreign laowang$ swipl-ld -shared -c++ g++ -o hello.so hello.cpp
Arthurs-MacBook-Pro:foreign laowang$ which swipl-ld
/usr/local/bin/swipl-ld
Arthurs-MacBook-Pro:foreign laowang$

------------------------- swipl toplevel records --------------
Arthurs-MacBook-Pro:foreign laowang$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.3-15-ge67699a08)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).
?- load_foreign_library(‘hello.so’).
true.

?- hello.
Hello!
true.

?- load_foreign_library(‘hello.so’).
ERROR: No install function in ‘/Users/laowang/learning/swipl/foreign/hello.so’
ERROR: Tried: [install_hello,install]
ERROR: In:
ERROR: [13] throw(error(existence_error(foreign_install_function,…),_7502))
ERROR: [11]
ERROR: [10] with_mutex(’$foreign’,load_foreign_library(‘hello.so’,user,default(install)))
ERROR: [7]
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
?- use_foreign_library(‘hello.so’).
ERROR: Initialization goal shlib:load_foreign_library(user:‘hello.so’) raised exception:
ERROR: No install function in ‘/Users/laowang/learning/swipl/foreign/hello.so’
ERROR: Tried: [install_hello,install]
ERROR: In:
ERROR: [20] throw(error(existence_error(foreign_install_function,…),_10786))
ERROR: [18]
ERROR: [17] with_mutex(’$foreign’,load_foreign_library(‘hello.so’,user,default(install)))
ERROR: [14] ‘$run_init_goal’(shlib:load_foreign_library(…)) at /usr/local/lib/swipl/boot/init.pl:618
ERROR: [13] catch(system:’$run_init_goal’(…),_10914,system:’$initialization_error’(_10936,…,-)) at /usr/local/lib/swipl/boot/init.pl:386
ERROR: [12] catch_with_backtrace(system:’$run_init_goal’(…),_10966,system:’$initialization_error’(_10988,…,-)) at /usr/local/lib/swipl/boot/init.pl:436
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
true.

?-
----------------------------------- reload_foreign_libraries not working —

  1. I modified hello.cpp as follows
    std::cout << “Hello world!” << std::endl;
  2. rebuilt the lib via swipl-ld
  3. in swipl,
    ?- reload_foreign_libraries.
    true.

?- hello.
Hello!
true.

update not working.

------------------------- make neither works -----------
in swipl,
?- make.
% Updating index for library /usr/local/lib/swipl/library/
true.

?- hello.
Hello!
true.


Appreciate for any helps.

With best wishes,
Arthur Wang

I pushed a fix that makes loaded C++ shared objects visible using current_foreign_library/2. That allows you can call load_foreign_library/1 multiple times without error, but the second call has no effect (as with C).

There is no make support for updating loaded shared objects. You can use unload_foreign_library/1, with this patch this seems to work for C++ as well. If the code uses no global variables and does not install any hooks, updating using unload/load should work. In general this is a rather dangerous operation though. You could implement this as a hook into make/0, using current_foreign_library/2 to find the loaded libraries, examine the times and unload/load.

P.s. Please use markdown syntax, otherwise half of you post becomes unreadable. Notably indent code blocks or use ``` before and after.

Hi Jan,
Thank you very much for your quick response.
unload/load works well now.
I’m still confused by unload_foreign_library/1,2 that seems always return ‘false’ and current_foreign_library/2 still unify ‘unloaded’ lib.

?- unload_foreign_library('test.so').
false.
?- current_foreign_library(test, _).
true.

I found that unload/load/current must specify the same file name as their arguments.
Thank you !

Yip. And you should typically leave the extension to the system. Also swipl-ld -shared will use the extension that is right for the platform.