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

Granular wrapping of the R api #240

Open
1 of 2 tasks
CGMossa opened this issue May 10, 2024 · 1 comment
Open
1 of 2 tasks

Granular wrapping of the R api #240

CGMossa opened this issue May 10, 2024 · 1 comment

Comments

@CGMossa
Copy link
Member

CGMossa commented May 10, 2024

It has been a long-term goal of mine, to include the totality of the R C-API in libR-sys.
Right now, libR-sys only serves as a sys-crate for extendr, and it primarily follows the needs of extendr.

But it would be nice if libR-sys could be used for all R-API needs in Rust.

To that end, I've made a prototype of how such a project can look like, see
https://github.com/CGMossa/modern_libr
(see discord discussion for reference)
https://discord.com/channels/751419551132155925/751419551132155928/1136068899507540078

Essentially, the resulting lib.rs will roughly look like this

Details

#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(ambiguous_glob_reexports)]

pub mod bindings {
    #[path = "R.rs"]
    pub mod r;

    #[path = "Rinternals.rs"]
    pub mod r_internals {
        use super::r_ext::boolean::Rboolean;
        use super::r_ext::complex::Rcomplex;
        use super::r_ext::r_dynload::DL_FUNC;

        include!("bindings/Rinternals.rs");
    }

    #[path = "Rmath.rs"]
    pub mod r_math;

    #[path = "Rversion.rs"]
    pub mod r_version;

    //TODO: unix specific?
    // #[path = "Rinterface.rs"]
    // pub mod r_interface;
    // pub use r_interface::*;

    pub mod r_embedded {
        use super::r_ext::boolean::Rboolean;

        include!("bindings/Rembedded.rs");
    }

    #[path = "R_ext"]
    pub mod r_ext {
        pub mod applic {
            use super::boolean::Rboolean;
            include!("bindings/R_ext/Applic.rs");
        }

        pub mod blas {
            use super::complex::Rcomplex;
            include!("bindings/R_ext/BLAS.rs");
        }

        // #[path = "Callbacks.rs"]
        pub mod callbacks {
            use super::super::r_internals::SEXP;
            use super::boolean::Rboolean;

            include!("bindings/R_ext/Callbacks.rs");
        }

        //TODO: another platform?
        // #[path = "GetX11Image.rs"]
        // pub mod GetX11Image;

        // #[path ="Lapack.rs"]
        pub mod lapack {
            use super::complex::Rcomplex;
            include!("bindings/R_ext/Lapack.rs");
        }

        #[path = "Linpack.rs"]
        pub mod linpack;

        #[path = "Parse.rs"]
        pub mod parse {
            use super::super::r_internals::SEXP;
            include!("bindings/R_ext/Parse.rs");
        }

        pub mod r_startup {
            use super::boolean::Rboolean;
            include!("bindings/R_ext/RStartup.rs");
        }

        pub mod r_dynload {
            use super::boolean::Rboolean;
            include!("bindings/R_ext/Rdynload.rs");
        }

        #[path = "Riconv.rs"]
        pub mod r_iconv;

        #[path = "Visibility.rs"]
        pub mod visibility;

        // TODO: another platform?
        // #[path ="eventloop.rs"]
        // pub mod event_loop;

        #[path = "Boolean.rs"]
        pub mod boolean;

        #[path = "Complex.rs"]
        pub mod complex;

        #[path = "Arith.rs"]
        pub mod arith;

        #[path = "Constants.rs"]
        pub mod constants;

        #[path = "Error.rs"]
        pub mod error;

        #[path = "Memory.rs"]
        pub mod memory;

        #[path = "Print.rs"]
        pub mod print;

        #[path = "RS.rs"]
        pub mod rs;

        #[path = "Random.rs"]
        pub mod random;

        #[path = "Utils.rs"]
        pub mod utils {
            use super::complex::Rcomplex;
            use super::boolean::Rboolean;

            include!("bindings/R_ext/Utils.rs");
        }

        //TODO: this is windows specific.
        #[path = "libextern.rs"]
        pub mod libextern;
    }

    #[path = "Rconfig.rs"]
    pub mod r_config;

    pub mod r_prelude {
        pub use super::r_config::*;
        pub use super::r_ext::arith::*;
        pub use super::r_ext::boolean::*;
        pub use super::r_ext::complex::*;
        pub use super::r_ext::constants::*;
        pub use super::r_ext::error::*;
        pub use super::r_ext::libextern::*;
        pub use super::r_ext::memory::*;
        pub use super::r_ext::print::*;
        pub use super::r_ext::random::*;
        pub use super::r_ext::rs::*;
        pub use super::r_ext::utils::*;
    }
}

There are challenges that need to be dealt with before this can be a reality:

  • Faster processing of bindings, as right now, in modern_libr uses clang to filter out elements. Luckily, we are about to land Remove clang-sys dependency #238 that serves as a schematic for how to accomplish this.
  • Paths to module-files has to be target, R version and platform dependent. This means that the module notation of #[path = <path>] has to depend on these things, for the seamless experience, that is.
@CGMossa
Copy link
Member Author

CGMossa commented Jun 10, 2024

This effort is continued in #242. While it looks like we are close to this goal, this might not be merged right away.

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

No branches or pull requests

1 participant