Thanks,
Apparently all solutions require some sort of the global variable. However during my evening experiments I was able to get the solution which does not require explicit creation of the global variable, but using allocation in the particular GC generation.
Here is the code for the call of the foreign function supplying Lisp callback. I create the object (Lisp struct) in long-living GC generation (2), take the address to it, allocate memory to hold the address and supply pointer to the foreign function(note the code is for 32bit LW):
;; create the object in "static" memory. generation 2 supposed to be safe from GC move
(allocation-in-gen-num 2
(let* ((helper (make-visitor-helper))
(helper-addr (sys:object-address helper))) ; get the object address
;; allocate dynamic memory for address and copy it here
(fli:with-integer-bytes (p len) helper-addr
;; call the foreign function 'visitchildren' supplying our callback 'visitor'
(visitchildren visitor
p))))
In my Lisp callable function I do the reverse: dereference the pointer to get the integer value (address in the generation 2) and then get the object by using this address:
;; check if the data supplied is not a null pointer
(unless (fli:null-pointer-p client-data)
;; dereference the opaque pointer to integer and get the value
(when-let* ((addr (fli:dereference client-data :type '(:unsigned :int)))
;; get the lisp object from address
(obj (sys:pointer-from-address addr)))
;; works!
(format t "filename: ~a~%" (visitor-helper-filename obj))))
BR
/Alexey