如何最终确定 lisp:struct 包含一个指针?

How to finalize lisp:struct containing a pointer?

我正在移植 Lightweight Communications and Marshalling from julia to lisp as it has a better API. I used swig 以生成 C 函数调用。

我想知道这是否是 C 指针的安全用法。这是创建函数:

(defun create-lcm (&optional (provider (null-pointer)))
    (let* ((ptr (lcm_create provider))
           (addr (cffi:pointer-address ptr)))
        (tg:finalize ptr (lambda () (lcm_destroy (cffi:make-pointer addr))))
        (if (NULL-POINTER-P ptr)
                (error "lcm creation error"))
        (%create-lcm :pointer ptr :provider provider
                                 :file-descriptor (lcm_get_fileno ptr))))

问题:

欢迎任何其他 notes/advices。

提前致谢。

以下是一些错误的地方:

  1. 将终结器附加到可能为空的指针
  2. 我不确定是否允许将终结器附加到外部指针。也许你是。
  3. 您需要小心使用终结器和 gc。如果终结器引用它终结的对象,那么对象和它的终结器会保持彼此存活(它们不能立即被收集,因为终结器可能会在某处存储对该对象的引用,然后该对象将存活,因此不应该'尚未最终确定。

我不知道这样对不对,但是更好:

(defun create-lcm (&optional (provider (null-pointer))
  (let ((ptr (lcm_create provider)))
    (when (null-pointer-p ptr)
      (error “lcm creation error”))
    (flet ((finaliser () (lcm_destroy ptr)))
      (let ((result (%create-lcm :pointer ptr :provider provider
                                 :file-descriptor (lcm_get_fileno ptr))))
        (tg:finalize result #'finaliser)
        result))))

这里有一些错误的地方:

  1. 如果 %create-lcmlcm_get_fileno 出现错误,则终结器不会 运行

您可能想阅读有关 cl-autowrap, which is used notably to wrap the SDL 2 in cl-sdl2 的内容。该库提供了围绕指针的薄包装器,这些指针在完成时已经释放了内存。

我还认为使用终结器的推荐方法只是将它们用于清除可能的泄漏,因为您几乎无法控制何时以及如何执行清除功能(例如,哪个线程,哪个动态环境) .

管理内存的一种方法是提前分配您的结构,并在您不再需要它们时清理它们(一个池)。或者您可以定义一个函数或宏来定义一个范围,以便在进入时分配内存并在退出时释放内存,使用 unwind-protect:

(defmacro with-lcm ((context &rest options) &body body)
  (let ((internal (gensym))) 
    `(let* ((,internal (create-lcm ,@options))
            (,context ,internal))
       (unwind-protect (progn ,@body)
         (destroy-lcm ,internal)))))