@@ -6,6 +6,8 @@ use std::{
66 sync:: { Mutex , RwLock , Arc } ,
77} ;
88
9+ use emacs_module:: emacs_finalizer_function;
10+
911use super :: * ;
1012use crate :: ErrorKind ;
1113
@@ -74,7 +76,7 @@ impl<T: Transfer> IntoLisp<'_> for Box<T> {
7476 let raw = Box :: into_raw ( self ) ;
7577 let ptr = raw as * mut os:: raw:: c_void ;
7678 // Safety: self is forgotten by `into_raw`, so it's safe for the GC to take over.
77- unsafe_raw_call_value ! ( env , make_user_ptr , Some ( finalize:: <T >) , ptr)
79+ unsafe { env . make_user_ptr ( Some ( finalize :: < T > ) , ptr) }
7880 }
7981}
8082
@@ -99,16 +101,55 @@ enable_transfers! {
99101 Arc ;
100102}
101103
102- type Finalizer = unsafe extern "C" fn ( ptr : * mut os:: raw:: c_void ) ;
104+ impl Env {
105+ /// Creates and returns a `user-ptr` object that wraps the raw pointer `ptr`. When the object is
106+ /// garbage-collected, `fin` will be called with `ptr` as the only argument. If `fin` is None,
107+ /// no finalization will be done.
108+ ///
109+ /// In general, prefer the `user-ptr` supported provided by the [`defun`] attr macro. Use this
110+ /// function only for special `user-ptr` types, such as newtypes wrapping opaque pointers.
111+ ///
112+ /// # Safety
113+ ///
114+ /// The pointer must be valid until the finalizer is called. The finalizer itself must finalize
115+ /// the pointer in a safe manner.
116+ ///
117+ /// [`defun`]: /emacs-macros/*/emacs_macros/attr.defun.html
118+ #[ allow( unused_unsafe) ]
119+ #[ inline]
120+ pub unsafe fn make_user_ptr ( & self , fin : emacs_finalizer_function , ptr : * mut os:: raw:: c_void ) -> Result < Value > {
121+ unsafe_raw_call_value ! ( self , make_user_ptr, fin, ptr)
122+ }
123+ }
103124
104125impl < ' e > Value < ' e > {
126+ /// Returns the raw pointer wrapped in this `user-ptr` object.
127+ ///
128+ /// In general, prefer the `user-ptr` supported provided by the [`defun`] attr macro. Use this
129+ /// function only for special `user-ptr` types, such as newtypes wrapping opaque pointers.
130+ ///
131+ /// [`defun`]: /emacs-macros/*/emacs_macros/attr.defun.html
132+ #[ inline]
133+ pub fn get_user_ptr ( self ) -> Result < * mut os:: raw:: c_void > {
134+ unsafe_raw_call ! ( self . env, get_user_ptr, self . raw)
135+ }
136+
137+ /// Returns the finalizer function associated with this `user-ptr` object.
138+ ///
139+ /// In general, prefer the `user-ptr` supported provided by the [`defun`] attr macro. Use this
140+ /// function only for special `user-ptr` types, such as newtypes wrapping opaque pointers.
141+ ///
142+ /// [`defun`]: /emacs-macros/*/emacs_macros/attr.defun.html
143+ #[ inline]
144+ pub fn get_user_finalizer ( self ) -> Result < emacs_finalizer_function > {
145+ unsafe_raw_call ! ( self . env, get_user_finalizer, self . raw)
146+ }
147+
105148 pub ( crate ) fn get_raw_pointer < T : Transfer > ( self ) -> Result < * mut T > {
106- let env = self . env ;
107- let raw = self . raw ;
108- match unsafe_raw_call ! ( env, get_user_finalizer, raw) ? {
149+ match self . get_user_finalizer ( ) ? {
109150 // TODO: Consider using dynamic dispatch for finalize, and core::any for type checking.
110- Some :: < Finalizer > ( fin) if fin == finalize :: < T > => {
111- let ptr: * mut os :: raw :: c_void = unsafe_raw_call ! ( env , get_user_ptr, raw ) ?;
151+ Some ( fin) if fin == finalize :: < T > => {
152+ let ptr = self . get_user_ptr ( ) ?;
112153 Ok ( ptr as * mut T )
113154 }
114155 _ => {
0 commit comments