Skip to content

Commit

Permalink
Unwrapping extptr stored in capsules
Browse files Browse the repository at this point in the history
  • Loading branch information
llaniewski committed Jan 9, 2024
1 parent 7b3e24f commit 9b2c8d4
Showing 1 changed file with 19 additions and 1 deletion.
20 changes: 19 additions & 1 deletion src/python.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ SEXP py_fetch_error(bool maybe_reuse_cached_r_trace = false);


const char *r_object_string = "r_object";
const char *r_extptr_string = "r_extptr";

// wrap an R object in a longer-lived python object "capsule"
SEXP py_capsule_read(PyObject* capsule) {
Expand All @@ -121,6 +122,14 @@ SEXP py_capsule_read(PyObject* capsule) {

}

// for a extptr stored in a capsule, use the R object stored in the capsule's context
SEXP py_extptr_capsule_read(PyObject* capsule) {
SEXP object = (SEXP) PyCapsule_GetContext(capsule);
if (object == NULL)
throw PythonException(py_fetch_error());
return TAG(object);
}

tthread::thread::id s_main_thread = 0;
bool is_main_thread() {
if (s_main_thread == 0)
Expand Down Expand Up @@ -192,6 +201,10 @@ bool is_r_object_capsule(PyObject* capsule) {
return PyCapsule_IsValid(capsule, r_object_string);
}

bool is_r_extptr_capsule(PyObject* capsule) {
return PyCapsule_IsValid(capsule, r_extptr_string);
}

// helper class for ensuring decref of PyObject in the current scope
template <typename T>
class PyPtr {
Expand Down Expand Up @@ -1405,6 +1418,11 @@ SEXP py_to_r(PyObject* x, bool convert) {
return py_capsule_read(x);
}

// external pointer
else if (is_r_extptr_capsule(x)) {
return py_extptr_capsule_read(x);
}

// default is to return opaque wrapper to python object. we pass convert = true
// because if we hit this code then conversion has been either implicitly
// or explicitly requested.
Expand Down Expand Up @@ -1708,7 +1726,7 @@ static PyObject* r_extptr_capsule(SEXP sexp) {

sexp = Rcpp_precious_preserve(sexp);

PyObject* capsule = PyCapsule_New(ptr, NULL, free_r_extptr_capsule);
PyObject* capsule = PyCapsule_New(ptr, r_extptr_string, free_r_extptr_capsule);
PyCapsule_SetContext(capsule, (void*)sexp);
return capsule;

Expand Down

0 comments on commit 9b2c8d4

Please sign in to comment.