r-lib / cpp11

cpp11 helps you to interact with R objects using C++ code.
https://cpp11.r-lib.org/
Other
193 stars 46 forks source link

[Feature Request] colnames and rownames wrappers #273

Open pachadotdev opened 2 years ago

pachadotdev commented 2 years ago

Such as it's the case for names(), it would be extremely convenient to have rownames() and colnames() in cpp codes.

My idea (sorry that I don't enough C++) would be like:

// THIS WORKS
[[cpp11::register]]
doubles cpp_names(writable::doubles X) {
    X.attr("names") = {"a","b"};
    return X;
}

// THIS WON'T
// [[cpp11::register]]
// doubles_matrix<> cpp_colnames(writable::doubles_matrix<> X) {
//     writable::list dimnames;
//     dimnames.push_back(NULL);
//     dimnames.push_back({"a","b"});
//     X.attr("dimnames") = dimnames;
//     return X;
// }
stephematician commented 1 year ago

Furthermore .... attributes can't be set on matrices. For example:

// set_and_get.cpp
#include "cpp11.hpp"

using namespace cpp11;

[[cpp11::register]]
sexp set_and_get_attr() {
    writable::doubles_matrix<> Y(0,0);
    Y.attr("my-attr") = writable::strings({"hello"}); 
    return Y.attr("my-attr");
}

Then in R:

cpp11::cpp_source('set_and_get.cpp')
set_and_get_attr()
# NULL

To set attributes, I think something like moving (or maybe copying? didn't try it) to a sexp works e.g.

// hacky_set_attr.cpp
#include "cpp11.hpp"

using namespace cpp11;

[[cpp11::register]]
sexp hacky_set_attr() {
    writable::doubles_matrix<> Y(0,0);
    sexp Y_sexp(std::move(Y.data()));
    Y_sexp.attr("my-attr") = "hello"; 
    return Y_sexp;
}

And in R:

cpp11::cpp_source('hacky_set_attr.cpp')
hacky_set_attr()
# <0 x 0 matrix>
# attr(,"my-attr")
# [1] "hello"

So basically some kind of 'upcasting'.

pachadotdev commented 1 year ago

Here's another reply from stackoverflow, @stephematician https://stackoverflow.com/a/76019987/3720258