extendr / extendr

R extension library for rust designed to be familiar to R users.
https://extendr.github.io
MIT License
425 stars 42 forks source link

More infrastructure needed for wrapper code #148

Closed clauswilke closed 3 years ago

clauswilke commented 3 years ago

The following features are still missing from the metadata code, I believe:

  1. Ability to determine whether an extendr function has a return value or not. Functions without return value need to return invisible().
  2. Ability to determine the name of the extendr module by calling a generic function (e.g., wrap__get_module_name). This is needed for rextendr.
Ilia-Kosenkov commented 3 years ago

@clauswilke, Could you please explain what is the issue with Rust functions returning nothing? Currently, such function is wrapped in invisible():

rextendr::rust_function("fn rust_fn() {}")
#> build directory: C:\Users\[redacted]\AppData\Local\Temp\RtmpkhrAfA\file398059da5d66
rust_fn()
print(rust_fn)
#> function() {
#>     invisible(.Call("wrap__rust_fn", PACKAGE = "rextendr1"))
#> }

Created on 2021-01-24 by the reprex package (v0.3.0) This build uses commit daee5c88.

clauswilke commented 3 years ago

The new wrapper framework that generates wrappers by a call to the compiled library doesn't add invisible(). Example:

library(extendrtests)

x <- MyClass$new()
x$set_a(10)
#> NULL
x$set_a
#> function(x) .Call(wrap__MyClass__set_a, self, x)
#> <environment: 0x7ff17c0b10b0>

Created on 2021-01-24 by the reprex package (v0.3.0)

I'd want to fix this before porting rextendr over.

clauswilke commented 3 years ago

Upon further reflection, maybe the second point is not a good idea. I'd like to be able to use multiple modules in one Rust library, and I believe the current code allows for that, but having a single function with unique name try to return multiple module names would be problematic (I think).

Fortunately I now see a fairly easy way to work around this in rextendr, so I think we're good. We do need point 1, though, information about whether the function returns a value or not.

clauswilke commented 3 years ago

If I read this line correctly, functions that don't return a value have a return type represented by the string "()": https://github.com/extendr/extendr/blob/37791965c4c3fe99b048a5225ce4e57bbcfa4e96/extendr-macros/src/lib.rs#L226

This then gets set here: https://github.com/extendr/extendr/blob/37791965c4c3fe99b048a5225ce4e57bbcfa4e96/extendr-macros/src/lib.rs#L390

And can be read here as func.return_type: https://github.com/extendr/extendr/blob/37791965c4c3fe99b048a5225ce4e57bbcfa4e96/extendr-api/src/metadata.rs#L119

clauswilke commented 3 years ago

Yup, this works. See #153.