Skip to content

Commit 5ee44bf

Browse files
committed
Add Env::make_user_ptr, Value::get_user_ptr, Value::get_user_finalizer
1 parent 7ffa511 commit 5ee44bf

File tree

2 files changed

+49
-7
lines changed

2 files changed

+49
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
55

66
## [Unreleased]
7+
- Added `Env::make_user_ptr`, `Value::get_user_ptr`, `Value::get_user_finalizer`.
78

89
## [0.12.0] - 2019-12-04
910
- Added `Env::make_vector` and `Env::vector` functions.

src/types/user_ptr.rs

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use std::{
66
sync::{Mutex, RwLock, Arc},
77
};
88

9+
use emacs_module::emacs_finalizer_function;
10+
911
use super::*;
1012
use 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

104125
impl<'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

Comments
 (0)