Reputation: 715
I want to use Common Lisp to process something for a C program. But for some reasons I need use SBCL.
I wonder how to correctly store a pointer to lisp object in system area memory which is allocated by a C function. For example,
struct c_struct {
...
lispobj *obj;
...
};
With sb-kernel:get-lisp-obj-address
, I can get the pointer to a lisp object. But it makes no sence to store it in foreign memory. The main problem is that GC moves objects. sb-sys:with-pinned-object
only pins objects during the extent of the body and it's obviously a bad idea to pin a object for a long time. So I need some methods to tell GC to update the pointer when the pointed object is moved.
Upvotes: 2
Views: 1226
Reputation: 13914
While I don't believe (although I'm eager to be corrected) that SBCL allows one to "pin" the pointer-address of an object for a very long time, nor is the garbage collector easily extensible to updating “foreign copies” of pointers to objects, you can obtain a persistent pointer to a Lisp callback function; i.e. a pointer which a C program can funcall
which is actually a Lisp function, using defcallback
.
One (untested) theory might be to wrap your C language calls in such a way:
c_struct
with a NULL pointer slot(defcallback …)
function pointer to your C program;
let's call it void with_locked_access ((void*) interior_function(struct c_struct *), struct c_struct *struct_to_use)
interior_function
with their own function-pointer interior_function
and the pointer to the c_struct
that interests theminterior_function
is actually (defcallback call-c-with-pinned-object…)
; it, in turn, calls sb-sys:with-pinned-object
and obtains the system-area pointer for the object, and stores it into c_struct
before calling interior_function
with the (now-populated) structure as its parameter.interior_function
does whatever it is that it wants the pinned Lisp object for; it returns, and call-c-with-pinned-object
closes out the with-pinned-object
form and returns, itself.Naturally, this depends entirely upon what it is you want to do in your C code, and whether it's going to be running in parallel with Lisp code that might be negatively impacted by the pinning, &c &c.
Alternatively, in the special (but common) case that the object in question happens to be a byte vector (e.g. perhaps a buffer of some kind), you might be able to take advantage of cffi-sys:make-shareable-byte-vector
and cffi-sys:with-pointer-to-vector-data
, q.v.
Upvotes: 1