Description
I tried this setting in linux:
src/rust/Cargo.toml: set crate type to cdylib
src/Makevars: Use Rust .so file directly
TARGET_DIR = ./rust/target
LIBDIR = $(TARGET_DIR)/release
RUSTLIB = $(LIBDIR)/librext.so
PKG_LIBS = -lrext
all: C_clean
$(SHLIB): $(RUSTLIB)
CARGOTMP = $(CURDIR)/.cargo
$(RUSTLIB):
if [ "$(NOT_CRAN)" != "true" ]; then \
export CARGO_HOME=$(CARGOTMP); \
fi && \
export PATH="$(PATH):$(HOME)/.cargo/bin" && \
cargo build --lib --release --manifest-path=./rust/Cargo.toml --target-dir $(TARGET_DIR) && \
cp $(RUSTLIB) $(SHLIB)
if [ "$(NOT_CRAN)" != "true" ]; then \
rm -Rf $(CARGOTMP) && \
rm -Rf $(LIBDIR)/build; \
fi
C_clean:
rm -Rf $(SHLIB) $(RUSTLIB) $(OBJECTS)
clean:
rm -Rf $(SHLIB) $(RUSTLIB) $(OBJECTS) $(TARGET_DIR)
export function in lib.rs
: (since I don't want to modify the original macro, I have to write another export function)
mod export {
#[no_mangle]
extern fn R_init_rext(dll:*const u8) { // if R_init_rext_extendr is renamed to R_init_rext, no need to write this.
unsafe {R_init_rext_extendr(dll)};
}
extern "C" {
fn R_init_rext_extendr(void:*const u8);
}
}
Steps:
- create a dir
rext
, cd to this dir, open R, executeusethis::create_package('.');rextendr::use_extendr('.');rextendr::document()
- delete generated
rext.so
,entrypoint.c/.o
- adding export function to
lib.rs
- edit
src/Makevars
andsrc/rust/Cargo.toml
- open R again, use
devtools::load_all('.')
to trigger package loading and compile the package - check whether
hello_world
function is usable
The check is successful, thus there might be no need to use entrypoint.*
.
Is it possible to remove the entry files?
What's more, the extendr_module!
grammar seems a little bit annoying. I have an attempt that use proc-macro to export all of them directly (just done!{}
at the end of lib.rs
is enough.) The issue is that, the current rust implementation may change and using global static variable might be disallowed in the future. I'm trying to examine the importance with rust developers, maybe we could simplify the grammar to something like exported!();
or done!();
directly in the future, if we found more use case about how to register a global function.