Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unwrapping extptr stored in capsules #1519

Merged
merged 3 commits into from
Jan 9, 2024
Merged

Conversation

llaniewski
Copy link
Contributor

R external pointers were wrapped as a python Capsule (in r_extptr_capsule(...)) but never properly unwrapped by py_to_r. As the r_extptr_capsule(...) function stores the pointer address in the Capsule, and the corresponding R object in the Capsule's "context" field, the original R external pointer can be easily retrieved. This preserves the external pointer's finaliser.

Example of usage:

library(Rcpp)
library(reticulate)

# Mock class for testing
Rcpp::sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;

class AClass {
public:
  AClass() {
    printf("AClass created\\n");
  }
  ~AClass() {
    printf("AClass destroyed\\n");
  }
};

// [[Rcpp::export]]
SEXP getA() {
  AClass* ptr = new AClass;
  return Rcpp::XPtr< AClass >(ptr);
}
')

x = getA() #<--- AClass created
xpy = r_to_py(x)
x_ = py_to_r(xpy)

identical(x,x_) #<--- TRUE

# Removing objects one by one with gc called to check when the C++ object is destroyed.
rm(x); for (i in 1:3) gc(full = TRUE);
rm(xpy); for (i in 1:3) gc(full = TRUE);
rm(x_); for (i in 1:3) gc(full = TRUE); #<--- AClass destroyed

This PR should not break any dependencies, as the capsule visible in python still stores the same pointer. I only changed its "name" field from NULL to "r_extptr" to easily identify it.
This PR fixes #1511

@t-kalinowski t-kalinowski merged commit efacf71 into rstudio:main Jan 9, 2024
12 checks passed
@t-kalinowski
Copy link
Member

Very nice, Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

py_to_r does not unwrap external pointer
2 participants