Hello Camm, *, I am testing your instructions to load and use an external library dynamically linked and I have a couple of issues. First, I am unable to load libjula.so because of an undefined symbol:
Use (help) to get some basic information on how to use GCL. Temporary directory for compiler files set to /tmp/ >(si:mdlsym "jl_init" "libjulia.so") Error: Fast links are on: do (si::use-fast-links nil) for debugging Signalled by SYSTEM:MDLSYM. Condition in SYSTEM:MDLSYM [or a callee]: INTERNAL-SIMPLE-ERROR: dlopen failure on "libjulia.so": "/usr/local/lib/libjulia.so: undefined symbol: jl_pgcstack_static_semaphore" Broken at SYSTEM:MDLSYM. Type :H for Help. 1 Return to top level. This is the same with your macro below. This does not happen with SBCL, Clozure CL or pure C (just tested). I looked at the Julia code and it almost not used; the only pieces of code (MIT licence) are: In a header file: #if !defined(_OS_DARWIN_) && !defined(_OS_WINDOWS_) #define JULIA_DEFINE_FAST_TLS \ static __attribute__((tls_model("local-exec"))) __thread jl_gcframe_t **jl_pgcstack_localexec; \ JL_DLLEXPORT _Atomic(char) jl_pgcstack_static_semaphore; \ JL_DLLEXPORT jl_gcframe_t **jl_get_pgcstack_static(void) \ { \ return jl_pgcstack_localexec; \ } \ JL_DLLEXPORT jl_gcframe_t ***jl_pgcstack_addr_static(void) \ { \ return &jl_pgcstack_localexec; \ } #else #define JULIA_DEFINE_FAST_TLS #endif and in a C file: #if !defined(_OS_WINDOWS_) && !defined(_OS_DARWIN_) void (*jl_pgcstack_setkey)(void*, void*(*)(void)) = lookup_symbol( libjulia_internal, "jl_pgcstack_setkey"); if (jl_pgcstack_setkey == NULL) { jl_loader_print_stderr("ERROR: Cannot find jl_pgcstack_setkey() function within libjulia-internal!\n"); exit(1); } void *fptr = lookup_symbol(RTLD_DEFAULT, "jl_get_pgcstack_static"); void *(*key)(void) = lookup_symbol(RTLD_DEFAULT, "jl_pgcstack_addr_static"); _Atomic(char) *semaphore = lookup_symbol(RTLD_DEFAULT, "jl_pgcstack_static_semaphore"); if (fptr != NULL && key != NULL && semaphore != NULL) { char already_used = 0; atomic_compare_exchange_strong(semaphore, &already_used, 1); if (already_used == 0) // RMW succeeded - we have exclusive access jl_pgcstack_setkey(fptr, key); } #endif So, since it seems to me it is just an optimization, for experimental purpose, I removed those pieces of code and rebuilt Julia and was able to load libjulia. I still wonder why GCL, contrary to the mentioned CL implementations, encounters the error above: undefined symbol. The second issue is related to the macro you mentioned below, I cannot give a path to the library at run time: (si::defdlfun (:void "jl_init" (|make_absolute_filename| "/lib/julia_wrap.so")) :void) julia_wrap.so is in a FriCAS lib directory and not in the ld library path so I need to give the full path. Here '(|make_absolute_filename| "/lib/julia_wrap.so")' is not executed so GCLcomplains about the fact it's not of type STRING. Accessory I do not know if ':void' instead of ':void*' can be used. I tested the two. Do you think I need to use more low-level operations with lib-name, mdl etc. the one used above in GCL, etc. and in fact, I do not know how? julia_wrap.so is a wrapper linked against libjulia, and dload-ed by FriCAS, it's necessary, see some examples here eventually: https://docs.julialang.org/en/v1/manual/embedding/ Maybe later I will ask some other questions about the GCL garbage collector to know if there is a "terminate" hook in it, I need it, I have two interface types in my Julia interface one where Julia operates directly on CL arrays, and another one where datas are in the Julia process stored in a hashed dictionary, so when GCL is GC-ing CL variables (a very simple class object in my interface that contains the key) I need to inform the Julia GC it can also GC them, i.e. delete them from the dictionary. Hoping I am relatively clear, regards, - Greg Le jeu. 29 mai 2025 à 22:23, Camm Maguire <c...@maguirefamily.org> a écrit : > Greetings! > > Grégory Vanuxem <g.vanu...@gmail.com> writes: > > > Hi Waldek, > > > > Many thanks for this quick response and fix. Just tested on official > FriCAS and the 2 problems you mentioned previously gone away. > > > > The .fricas.input file is still not "read" but for my mid-term work it > is not a big problem, my startup file is just displaying computation times > and augmenting line > > length of output to 110. Maybe this is related to my Kali distribution > on WSL2, I don't know. > > > > The )read command is to blame on my settings: > > > > (1) -> )sys pws > > > > >> System error: > > INTERNAL-SIMPLE-ERROR: The assertion !posix_spawnp(&pid, *p1, > &file_actions, &attr, (void *)p1, environ) on line 65 of o/unixsys.c in > function vsystem failed: > > No such file or directory > > > > (1) -> )sys pwd > > /home/greg > > (1) -> )sys ls -l .fricas.input > > -rw-r--r-- 1 greg greg 35 Feb 11 09:42 .fricas.input > > (1) -> )read .fricas.input > > > > The file .fricas.input is needed but does not exist. > > > > BTW great improvements have been done for gcl-2.7.1, thanks to you and > > Camm, it's a very good thing for me since I plan to code a wrapper in > > Common Lisp using my C wrapper to Julia compatible with GCL. I did one > > for Axiom in the past, a coding LISP game for me containing only > > "and", "or "and "not" keywords (no > > Most happy to see a satisfied customer! > > > loops or conditionals). A direct wrapper to Fortran BLAS in fact. Now > > I have to look at documentation changes for the GCL-2.7 series FFI. > > > > I turn your attention to defdlfun. In 2.7.x we can establish persistent > (across image saves) bindings to new external shared libraries on the > fly, with the call overhead being a single pointer dereference: > > > >(describe 'defdlfun) > > DEFDLFUN - internal symbol in COMMON-LISP-USER package > From ((DEFDLFUN . External Shared Libraries) gcl-si.info): > > -- Macro: DEFDLFUN > Package:SYSTEM > > Syntax: > (compile (DEFDLFUN {RETURN NAME &optional LIBNAME) ARGS*)) > > GCL specific: Produces an entry function to function NAME in > external shared library LIBNAME with the specified args/return > signature. This function must be compiled to run. When inlined, > the function call collapses to a single reference to a pointer > which is automatically updated to the location of the external > function at image startup. The connection to the external library > is persistent across image saves and re-executions. The RETURN and > ARGS specifiers are keywords from the following list corresponding > to the accompanying C programming types: > > :char :short :int :long :float :double > > Unsigned versions available are: > > :uchar :ushort :uint > > Complex float and complex double types can be access via: > > :fcomplex :dcomples > > Pointers to types available are > > :void* :char* :long* :float* :double* > > Example usage: > > > > > GCL (GNU Common Lisp) 2.7.0 Thu Oct 26 12:00:01 PM EDT 2023 > CLtL1 git: Version_2_7_0pre38 > Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl) > Binary License: GPL due to GPL'ed components: (XGCL READLINE > UNEXEC) > Modifications of this banner must retain notice of a compatible > license > Dedicated to the memory of W. Schelter > > Use (help) to get some basic information on how to use GCL. > Temporary directory for compiler files set to /tmp/ > > >(do-symbols (s :lib) (print s)) > > LIB:|libm| > LIB:|libc| > NIL > > >(compile (si::defdlfun (:double "cblas_ddot" "libblas.so") > :uint :double* :uint :double* :uint)) > > ;; Compiling /tmp/gazonk_653784_0.lsp. > ;; End of Pass 1. > ;; End of Pass 2. > OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, > Speed=3 > ;; Finished compiling /tmp/gazonk_653784_0.o. > ;; Loading #P"/tmp/gazonk_653784_0.o" > ;; start address for /tmp/gazonk_653784_0.o 0x2700860 > ;; Finished loading #P"/tmp/gazonk_653784_0.o" > #<function 0000000001a4a860> > NIL > NIL > > >(do-symbols (s :lib) (print s)) > > LIB:|libblas| > LIB:|libm| > LIB:|libc| > NIL > > >(do-symbols (s 'lib::|libblas|) (unless (find-symbol > (symbol-name s) :user) (print s))) > > |libblas|:|cblas_ddot| > NIL > NIL > > >(setq a (make-array 3 :element-type 'long-float) b (make-array > 3 :element-type 'long-float)) > > #(0.0 0.0 0.0) > > >(setf (aref a 1) 1.2 (aref b 1) 2.3) > > 2.3 > > >(|libblas|:|cblas_ddot| 3 a 1 b 1) > > 2.76 > > >(compile (defun foo (a b) (declare ((vector long-float) a b)) > (|libblas|:|cblas_ddot| (length a) a 1 b 1))) > > ;; Compiling /tmp/gazonk_653784_0.lsp. > ;; End of Pass 1. > ;; End of Pass 2. > OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, > Speed=3 > ;; Finished compiling /tmp/gazonk_653784_0.o. > ;; Loading #P"/tmp/gazonk_653784_0.o" > ;; start address for /tmp/gazonk_653784_0.o 0x2715050 > ;; Finished loading #P"/tmp/gazonk_653784_0.o" > #<function 0000000001a62140> > NIL > NIL > > >(compile (defun bar (a b) (declare (inline > |libblas|:|cblas_ddot|) ((vector long-float) a b)) (|libblas|:|cblas_ddot| > (length a) a 1 b 1))) > > ;; Compiling /tmp/gazonk_653784_0.lsp. > ;; End of Pass 1. > ;; End of Pass 2. > OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, > Speed=3 > ;; Finished compiling /tmp/gazonk_653784_0.o. > ;; Loading #P"/tmp/gazonk_653784_0.o" > ;; start address for /tmp/gazonk_653784_0.o 0x2729570 > ;; Finished loading #P"/tmp/gazonk_653784_0.o" > #<function 0000000001a62740> > NIL > NIL > > >(foo a b) > > 2.76 > > >(bar a b) > > 2.76 > > >(setq compiler::*disassemble-objdump* nil) > > NIL > > >(disassemble '|libblas|:|cblas_ddot|) > > ;; Compiling /tmp/gazonk_653784_0.lsp. > ;; End of Pass 1. > ;; End of Pass 2. > OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, > Speed=3 > ;; Finished compiling /tmp/gazonk_653784_0.o. > > #include "gazonk_653784_0.h" > void init_code(){do_init((void *)VV);} > /* local entry for function libblas::cblas_ddot */ > > static object LI1__cblas_ddot___gazonk_653784_0(fixnum V6,object > V7,fixnum V8,object V9,fixnum V10) > { VMB1 VMS1 VMV1 > if(!(((char)tp0(make_fixnum(V6)))==(1))){ > goto T8; > } > if(!((0)<=(V6))){ > goto T13; > } > if(!((V6)<=((fixnum)4294967295))){ > goto T11; > } > goto T12; > > goto T13; > T13:; > goto T11; > > goto T12; > T12:; > goto T7; > > goto T11; > T11:; > goto T6; > > goto T8; > T8:; > goto T6; > > goto T7; > T7:; > goto T5; > > goto T6; > T6:; > goto T3; > > goto T5; > T5:; > goto T2; > > goto T3; > T3:; > V11= CMPmake_fixnum(V6); > V6= fixint((fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL > */(object )(*LnkLI2)(((object)VV[1]),(V11),((object)VV[2]),Cnil))); > goto T2; > T2:; > switch(tp6(V7)){ > case 428: > goto T27; > T27:; > case 492: > goto T28; > T28:; > goto T25; > > default: > goto T29; > T29:; > goto T24; > > goto T24; > } > goto T24; > > goto T25; > T25:; > goto T23; > > goto T24; > T24:; > goto T22; > > goto T23; > T23:; > goto T21; > > goto T22; > T22:; > goto T19; > > goto T21; > T21:; > goto T18; > > goto T19; > T19:; > V7= (fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object > )(*LnkLI2)(((object)VV[3]),(V7),((object)VV[4]),Cnil)); > goto T18; > T18:; > if(!(((char)tp0(make_fixnum(V8)))==(1))){ > goto T39; > } > if(!((0)<=(V8))){ > goto T44; > } > if(!((V8)<=((fixnum)4294967295))){ > goto T42; > } > goto T43; > > goto T44; > T44:; > goto T42; > > goto T43; > T43:; > goto T38; > > goto T42; > T42:; > goto T37; > > goto T39; > T39:; > goto T37; > > goto T38; > T38:; > goto T36; > > goto T37; > T37:; > goto T34; > > goto T36; > T36:; > goto T33; > > goto T34; > T34:; > V12= CMPmake_fixnum(V8); > V8= fixint((fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL > */(object )(*LnkLI2)(((object)VV[5]),(V12),((object)VV[2]),Cnil))); > goto T33; > T33:; > switch(tp6(V9)){ > case 428: > goto T58; > T58:; > case 492: > goto T59; > T59:; > goto T56; > > default: > goto T60; > T60:; > goto T55; > > goto T55; > } > goto T55; > > goto T56; > T56:; > goto T54; > > goto T55; > T55:; > goto T53; > > goto T54; > T54:; > goto T52; > > goto T53; > T53:; > goto T50; > > goto T52; > T52:; > goto T49; > > goto T50; > T50:; > V9= (fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL */(object > )(*LnkLI2)(((object)VV[6]),(V9),((object)VV[4]),Cnil)); > goto T49; > T49:; > if(!(((char)tp0(make_fixnum(V10)))==(1))){ > goto T70; > } > if(!((0)<=(V10))){ > goto T75; > } > if(!((V10)<=((fixnum)4294967295))){ > goto T73; > } > goto T74; > > goto T75; > T75:; > goto T73; > > goto T74; > T74:; > goto T69; > > goto T73; > T73:; > goto T68; > > goto T70; > T70:; > goto T68; > > goto T69; > T69:; > goto T67; > > goto T68; > T68:; > goto T65; > > goto T67; > T67:; > goto T64; > > goto T65; > T65:; > V13= CMPmake_fixnum(V10); > V10= fixint((fcall.argd=4,/* SYSTEM::CHECK-TYPE-SYMBOL > */(object )(*LnkLI2)(((object)VV[7]),(V13),((object)VV[2]),Cnil))); > goto T64; > T64:; > {object V14 = > make_longfloat(((double(*)(uint,double*,uint,double*,uint))(dlcblas_ddot))((uint)V6,(double*)V7->v.v_self,(uint)V8,(double*)V9->v.v_self,(uint)V10)); > VMR1(V14);} > } > static object LnkTLI2(object first,...){object V1;va_list > ap;va_start(ap,first);V1=(object > )call_proc_new(((object)VV[0]),0,262147,(void **)(void > *)&LnkLI2,0,first,ap);va_end(ap);return V1;} /* SYSTEM::CHECK-TYPE-SYMBOL */ > (9 (MAPC 'EVAL *COMPILER-COMPILE-DATA*)) > static object LI1__cblas_ddot___gazonk_653784_0(fixnum V6,object > V7,fixnum V8,object V9,fixnum V10) > ; > static void *dlcblas_ddot; > #define VMB1 object V13 ,V12 ,V11; > #define VMS1 > #define VMV1 > #define VMRV1(a_,b_) return((object )a_); > #define VMR1(a_) VMRV1(a_,0); > #define VM1 0 > static void * VVi[9]={ > #define Cdata VV[8] > (void *)(&dlcblas_ddot), > (void *)(LI1__cblas_ddot___gazonk_653784_0) > }; > #define VV (VVi) > static object LnkTLI2(object,...); > static object (*LnkLI2)() = (object (*)()) LnkTLI2; > NIL > > >(disassemble 'foo) > > ;; Compiling /tmp/gazonk_653784_0.lsp. > ;; End of Pass 1. > ;; End of Pass 2. > OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, > Speed=3 > ;; Finished compiling /tmp/gazonk_653784_0.o. > > #include "gazonk_653784_0.h" > void init_code(){do_init((void *)VV);} > /* local entry for function COMMON-LISP-USER::FOO */ > > static object LI1__FOO___gazonk_653784_0(object V3,object V4) > { VMB1 VMS1 VMV1 > > if(!(((char)((fixnum)((uchar*)((fixnum)V3))[(fixnum)2]&(fixnum)1))==(0))){ > goto T5; > } > goto T2; > > goto T5; > T5:; > V5= ((fixnum)((uint*)((fixnum)V3))[(fixnum)4]&268435455); > goto T1; > > goto T2; > T2:; > V5= > (((fixnum)((uint*)((fixnum)V3))[(fixnum)1]>>(fixnum)3)&268435455); > goto T1; > T1:; > {object V6 = (/* libblas::cblas_ddot */(object > )(*LnkLI2)(V5,(V3),(fixnum)1,(V4),(fixnum)1)); > VMR1(V6);} > } > static object LnkTLI2(object first,...){object V1;va_list > ap;va_start(ap,first);V1=(object )call_proc_new(((object)VV[0]),0,5,(void > **)(void *)&LnkLI2,1092,first,ap);va_end(ap);return V1;} /* > libblas::cblas_ddot */ > (2 (MAPC 'EVAL *COMPILER-COMPILE-DATA*)) > static object LI1__FOO___gazonk_653784_0(object V3,object V4) > ; > #define VMB1 fixnum V5; > #define VMS1 > #define VMV1 > #define VMRV1(a_,b_) return((object )a_); > #define VMR1(a_) VMRV1(a_,0); > #define VM1 0 > static void * VVi[2]={ > #define Cdata VV[1] > (void *)(LI1__FOO___gazonk_653784_0) > }; > #define VV (VVi) > static object LnkTLI2(object,...); > static object (*LnkLI2)() = (object (*)()) LnkTLI2; > NIL > > >(disassemble 'bar) > > ;; Compiling /tmp/gazonk_653784_0.lsp. > ;; End of Pass 1. > ;; End of Pass 2. > OPTIMIZE levels: Safety=0 (No runtime error checking), Space=0, > Speed=3 > ;; Finished compiling /tmp/gazonk_653784_0.o. > > #include "gazonk_653784_0.h" > void init_code(){do_init((void *)VV);} > /* local entry for function COMMON-LISP-USER::BAR */ > > static object LI1__BAR___gazonk_653784_0(object V3,object V4) > { VMB1 VMS1 VMV1 > {fixnum V5; > > if(!(((char)((fixnum)((uchar*)((fixnum)V3))[(fixnum)2]&(fixnum)1))==(0))){ > goto T5; > } > goto T2; > > goto T5; > T5:; > V5= ((fixnum)((uint*)((fixnum)V3))[(fixnum)4]&268435455); > goto T1; > > goto T2; > T2:; > V5= > (((fixnum)((uint*)((fixnum)V3))[(fixnum)1]>>(fixnum)3)&268435455); > goto T1; > T1:; > {object V6 = > make_longfloat(((double(*)(uint,double*,uint,double*,uint))(dlcblas_ddot))((uint)V5,(double*)V3->v.v_self,(uint)1,(double*)V4->v.v_self,(uint)1)); > VMR1(V6);}} > } > (2 (MAPC 'EVAL *COMPILER-COMPILE-DATA*)) > static object LI1__BAR___gazonk_653784_0(object V3,object V4) > ; > static void *dlcblas_ddot; > #define VMB1 > #define VMS1 > #define VMV1 > #define VMRV1(a_,b_) return((object )a_); > #define VMR1(a_) VMRV1(a_,0); > #define VM1 0 > static void * VVi[2]={ > #define Cdata VV[1] > (void *)(&dlcblas_ddot), > (void *)(LI1__BAR___gazonk_653784_0) > }; > #define VV (VVi) > NIL > > >(si::save-system "ff") > $ ./ff > GCL (GNU Common Lisp) 2.7.0 Thu Oct 26 12:00:01 PM EDT 2023 > CLtL1 git: Version_2_7_0pre38 > Source License: LGPL(gcl,gmp), GPL(unexec,bfd,xgcl) > Binary License: GPL due to GPL'ed components: (XGCL READLINE > UNEXEC) > Modifications of this banner must retain notice of a compatible > license > Dedicated to the memory of W. Schelter > > Use (help) to get some basic information on how to use GCL. > Temporary directory for compiler files set to /tmp/ > > >(foo a b) > > 2.76 > > >(bar a b) > > 2.76 > > > > > > Take care, > > > > > > > - Greg > > > > PS / I Cc-ed to gcl-devel > > > > Le sam. 24 mai 2025 à 15:30, Waldek Hebisch <de...@fricas.org> a écrit : > > > > On Fri, May 23, 2025 at 09:56:29PM +0200, Grégory Vanuxem wrote: > > > Hello, > > > > > > I don't know if you can reproduce this: if I start FriCAS from $HOME > it > > > starts nicely but if I start in another directory see the snippet > below. > > > I tried with gcl2.7.1-4 from a Debian based distribution and after > with the > > > official Debian sid and the same happens: > > > > > <snip> > > > > > > >> System error: > > > INTERNAL-SIMPLE-PARSE-ERROR: "/home/greg//.fricas.input" is not a > valid > > > pathname on host NIL > > > > > > > > > >> System error: > > > INTERNAL-SIMPLE-ERROR: The tag |top_level| is undefined. > > > > Should be fixed now. > > > > -- > > Waldek Hebisch > > > > -- > > You received this message because you are subscribed to the Google > Groups "FriCAS - computer algebra system" group. > > To unsubscribe from this group and stop receiving emails from it, send > an email to fricas-devel+unsubscr...@googlegroups.com. > > To view this discussion visit > https://groups.google.com/d/msgid/fricas-devel/aDHJ1HqJwLlykCMl%40fricas.org > . > > -- > Camm Maguire c...@maguirefamily.org > ========================================================================== > "The earth is but one country, and mankind its citizens." -- Baha'u'llah > > -- > You received this message because you are subscribed to the Google Groups > "FriCAS - computer algebra system" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to fricas-devel+unsubscr...@googlegroups.com. > To view this discussion visit > https://groups.google.com/d/msgid/fricas-devel/87cybryxm6.fsf%40maguirefamily.org > . >