cpp-0.5.6/.cargo_vcs_info.json0000644000000001121377257576000117010ustar { "git": { "sha1": "65b553eaaa2e9fa7acefe12e25ff47724005d057" } } cpp-0.5.6/Cargo.toml0000644000000020051377257576000077020ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "cpp" version = "0.5.6" authors = ["Nika Layzell ", "Olivier Goffart "] description = "Inline C++ code closures" documentation = "https://docs.rs/cpp" readme = "../README.md" keywords = ["c", "cxx", "ffi", "compiler"] categories = ["development-tools::ffi"] license = "MIT/Apache-2.0" repository = "https://github.com/mystor/rust-cpp" [dependencies.cpp_macros] version = "=0.5.6" [dev-dependencies.cpp_build] version = "=0.5.6" cpp-0.5.6/Cargo.toml.orig010064400017520001752000000010651377257547600134110ustar 00000000000000[package] name = "cpp" version = "0.5.6" authors = ["Nika Layzell ", "Olivier Goffart "] edition = "2018" description = "Inline C++ code closures" readme = "../README.md" license = "MIT/Apache-2.0" keywords = ["c", "cxx", "ffi", "compiler"] categories = ["development-tools::ffi"] repository = "https://github.com/mystor/rust-cpp" documentation = "https://docs.rs/cpp" [dependencies] cpp_macros = { version = "=0.5.6", path = "../cpp_macros" } [dev-dependencies] cpp_build = { version = "=0.5.6", path = "../cpp_build" } cpp-0.5.6/src/lib.rs010064600017520001752000000367441370254615700124260ustar 00000000000000//! This crate `cpp` provides macros that allow embedding arbitrary C++ code. //! //! # Usage //! //! This crate must be used in tandem with the [`cpp_build`](https://docs.rs/cpp_build) crate. A basic Cargo //! project which uses these projects would have a structure like the following: //! //! ```text //! crate //! |-- Cargo.toml //! |-- src //! |-- main.rs //! |-- build.rs //! ``` //! //! Where the files look like the following: //! //! #### Cargo.toml //! //! ```toml //! [package] //! build = "build.rs" //! //! [dependencies] //! cpp = "0.5" //! //! [build-dependencies] //! cpp_build = "0.5" //! ``` //! //! #### build.rs //! //! ```no_run //! extern crate cpp_build; //! //! fn main() { //! cpp_build::build("src/main.rs"); //! } //! ``` //! //! #### main.rs //! //! ```ignore //! # // tested in test/src/examples.rs //! use cpp::cpp; //! //! cpp!{{ //! #include //! }} //! //! fn main() { //! let name = std::ffi::CString::new("World").unwrap(); //! let name_ptr = name.as_ptr(); //! let r = unsafe { //! cpp!([name_ptr as "const char *"] -> u32 as "int32_t" { //! std::cout << "Hello, " << name_ptr << std::endl; //! return 42; //! }) //! }; //! assert_eq!(r, 42) //! } //! ``` //! //! # Build script //! //! Use the `cpp_build` crates from your `build.rs` script. //! The same version of `cpp_build` and `cpp` crates should be used. //! You can simply use the `cpp_build::build` function, or the `cpp_build::Config` //! struct if you want more option. //! //! Behind the scene, it uses the `cc` crate. //! //! ## Using external libraries //! //! Most likely you will want to link against external libraries. You need to tell cpp_build //! about the include path and other flags via `cpp_build::Config` and you need to let cargo //! know about the link. More info in the [cargo docs](https://doc.rust-lang.org/cargo/reference/build-scripts.html). //! //! Your `build.rs` could look like this: //! //! ```no_run //! fn main() { //! let include_path = "/usr/include/myexternallib"; //! let lib_path = "/usr/lib/myexternallib"; //! cpp_build::Config::new().include(include_path).build("src/lib.rs"); //! println!("cargo:rustc-link-search={}", lib_path); //! println!("cargo:rustc-link-lib=myexternallib"); //! } //! ``` //! //! (But you probably want to allow to configure the path via environment variables or //! find them using some external tool such as the `pkg-config` crate, instead of hardcoding //! them in the source) //! //! # Limitations //! //! As with all procedure macro crates we also need to parse Rust source files to //! extract C++ code. That leads to the fact that some of the language features //! might not be supported in full. One example is the attributes. Only a limited //! number of attributes is supported, namely: `#[path = "..."]` for `mod` //! declarations to specify an alternative path to the module file and //! `#[cfg(feature = "...")]` for `mod` declarations to conditionally include the //! module into the parsing process. Please note that the latter is only supported //! in its simplest form: straight-forward `feature = "..."` without any //! additional conditions, `cfg!` macros are also not supported at the moment. //! //! Since the C++ code is included within a rust file, the C++ code must obey both //! the Rust and the C++ lexing rules. For example, Rust supports nested block comments //! (`/* ... /* ... */ ... */`) while C++ does not, so nested comments not be used in the //! `cpp!` macro. Also the Rust lexer will not understand the C++ raw literal, nor all //! the C++ escape sequences within literal, so only string literals that are both valid //! in Rust and in C++ should be used. The same applies for group separators in numbers. //! Be careful to properly use `#if` / `#else` / `#endif`, and not have unbalanced delimiters. #![no_std] #[macro_use] #[allow(unused_imports)] extern crate cpp_macros; #[doc(hidden)] pub use cpp_macros::*; /// Internal macro which is used to locate the `rust!` invocations in the /// C++ code embedded in `cpp!` invocation, to translate them into `extern` /// functions #[doc(hidden)] #[macro_export] macro_rules! __cpp_internal { (@find_rust_macro [$($a:tt)*] rust!($($rust_body:tt)*) $($rest:tt)*) => { $crate::__cpp_internal!{ @expand_rust_macro [$($a)*] $($rust_body)* } $crate::__cpp_internal!{ @find_rust_macro [$($a)*] $($rest)* } }; (@find_rust_macro [$($a:tt)*] ( $($in:tt)* ) $($rest:tt)* ) => { $crate::__cpp_internal!{ @find_rust_macro [$($a)*] $($in)* $($rest)* } }; (@find_rust_macro [$($a:tt)*] [ $($in:tt)* ] $($rest:tt)* ) => { $crate::__cpp_internal!{ @find_rust_macro [$($a)*] $($in)* $($rest)* } }; (@find_rust_macro [$($a:tt)*] { $($in:tt)* } $($rest:tt)* ) => { $crate::__cpp_internal!{ @find_rust_macro [$($a)*] $($in)* $($rest)* } }; (@find_rust_macro [$($a:tt)*] $t:tt $($rest:tt)*) => { $crate::__cpp_internal!{ @find_rust_macro [$($a)*] $($rest)* } }; (@find_rust_macro [$($a:tt)*]) => {}; (@expand_rust_macro [$($a:tt)*] $i:ident [$($an:ident : $at:ty as $ac:tt),*] {$($body:tt)*}) => { #[allow(non_snake_case)] #[allow(unused_unsafe)] #[cfg_attr(feature = "cargo-clippy", allow(clippy::forget_copy))] #[cfg_attr(feature = "cargo-clippy", allow(clippy::forget_ref))] #[doc(hidden)] $($a)* unsafe extern "C" fn $i($($an : *const $at),*) { $(let $an : $at = unsafe { $an.read() };)* (|| { $($body)* })(); $(::core::mem::forget($an);)* } }; (@expand_rust_macro [$($a:tt)*] $i:ident [$($an:ident : $at:ty as $ac:tt),*] -> $rt:ty as $rc:tt {$($body:tt)*}) => { #[allow(non_snake_case)] #[allow(unused_unsafe)] #[cfg_attr(feature = "cargo-clippy", allow(clippy::forget_copy))] #[cfg_attr(feature = "cargo-clippy", allow(clippy::forget_ref))] #[doc(hidden)] $($a)* unsafe extern "C" fn $i($($an : *const $at, )* rt : *mut $rt) -> *mut $rt { $(let $an : $at = unsafe { $an.read() };)* { #[allow(unused_mut)] let mut lambda = || {$($body)*}; unsafe { ::core::ptr::write(rt, lambda()) }; } $(::core::mem::forget($an);)* rt } }; (@expand_rust_macro $($invalid:tt)*) => { compile_error!(concat!( "Cannot parse rust! macro: ", stringify!([ $($invalid)* ]) )) }; } /// This macro is used to embed arbitrary C++ code. /// /// There are two variants of the `cpp!` macro. The first variant is used for /// raw text inclusion. Text is included into the generated `C++` file in the /// order which they were defined, inlining module declarations. /// /// ```ignore /// cpp! {{ /// #include /// #include /// }} /// ``` /// /// The second variant is used to embed C++ code within Rust code. A list of /// variable names which should be captured are taken as the first argument, /// with their corresponding C++ type. The body is compiled as a C++ function. /// /// This variant of the macro may only be invoked in expression context, and /// requires an `unsafe` block, as it is performing FFI. /// /// ```ignore /// let y: i32 = 10; /// let mut z: i32 = 20; /// let x: i32 = unsafe { cpp!([y as "int32_t", mut z as "int32_t"] -> i32 as "int32_t" { /// z++; /// return y + z; /// })}; /// ``` /// /// You can also put the unsafe keyword as the first keyword of the `cpp!` macro, which /// has the same effect as putting the whole macro in an `unsafe` block: /// /// ```ignore /// let x: i32 = cpp!(unsafe [y as "int32_t", mut z as "int32_t"] -> i32 as "int32_t" { /// z++; /// return y + z; /// }); /// ``` /// /// ## rust! pseudo-macro /// /// The `cpp!` macro can contain, in the C++ code, a `rust!` sub-macro, which allows /// the inclusion of Rust code in C++ code. This is useful to /// implement callback or override virtual functions. Example: /// /// ```ignore /// trait MyTrait { /// fn compute_value(&self, x : i32) -> i32; /// } /// /// cpp!{{ /// struct TraitPtr { void *a,*b; }; /// class MyClassImpl : public MyClass { /// public: /// TraitPtr m_trait; /// int computeValue(int x) const override { /// return rust!(MCI_computeValue [m_trait : &MyTrait as "TraitPtr", x : i32 as "int"] /// -> i32 as "int" { /// m_trait.compute_value(x) /// }); /// } /// } /// }} /// ``` /// /// The syntax for the `rust!` macro is: /// ```ignore /// rust!($uniq_ident:ident [$($arg_name:ident : $arg_rust_type:ty as $arg_c_type:tt),*] /// $(-> $ret_rust_type:ty as $rust_c_type:tt)* {$($body:tt)*}) /// ``` /// `uniq_ident` is a unique identifier which will be used to name the `extern` function #[macro_export] macro_rules! cpp { // raw text inclusion ({$($body:tt)*}) => { $crate::__cpp_internal!{ @find_rust_macro [#[no_mangle] pub] $($body)*} }; // inline closure ([$($captures:tt)*] $($rest:tt)*) => { { $crate::__cpp_internal!{ @find_rust_macro [] $($rest)*} #[allow(unused)] #[derive($crate::__cpp_internal_closure)] enum CppClosureInput { Input = (stringify!([$($captures)*] $($rest)*), 0).1 } __cpp_closure_impl![$($captures)*] } }; // wrap unsafe (unsafe $($tail:tt)*) => { unsafe { cpp!($($tail)*) } }; } #[doc(hidden)] pub trait CppTrait { type BaseType; const ARRAY_SIZE: usize; const CPP_TYPE: &'static str; } /// This macro allows wrapping a relocatable C++ struct or class that might have /// a destructor or copy constructor, implementing the `Drop` and `Clone` trait /// appropriately. /// /// ```ignore /// cpp_class!(pub unsafe struct MyClass as "MyClass"); /// impl MyClass { /// fn new() -> Self { /// unsafe { cpp!([] -> MyClass as "MyClass" { return MyClass(); }) } /// } /// fn member_function(&self, param : i32) -> i32 { /// unsafe { cpp!([self as "const MyClass*", param as "int"] -> i32 as "int" { /// return self->member_function(param); /// }) } /// } /// } /// ``` /// /// This will create a Rust struct `MyClass`, which has the same size and /// alignment as the C++ class `MyClass`. It will also implement the `Drop` trait /// calling the destructor, the `Clone` trait calling the copy constructor, if the /// class is copyable (or `Copy` if it is trivially copyable), and `Default` if the class /// is default constructible /// /// ## Derived Traits /// /// The `Default`, `Clone` and `Copy` traits are implicitly implemented if the C++ /// type has the corresponding constructors. /// /// You can add the `#[derive(...)]` attribute in the macro in order to get automatic /// implementation of the following traits: /// /// * The trait `PartialEq` will call the C++ `operator==`. /// * You can add the trait `Eq` if the semantics of the C++ operator are those of `Eq` /// * The trait `PartialOrd` need the C++ `operator<` for that type. `lt`, `le`, `gt` and /// `ge` will use the corresponding C++ operator if it is defined, otherwise it will /// fallback to the less than operator. For PartialOrd::partial_cmp, the `operator<` will /// be called twice. Note that it will never return `None`. /// * The trait `Ord` can also be specified when the semantics of the `operator<` corresponds /// to a total order /// /// ## Safety Warning /// /// Use of this macro is highly unsafe. Only certain C++ classes can be bound /// to, C++ classes may perform arbitrary unsafe operations, and invariants are /// easy to break. /// /// A notable restriction is that this macro only works if the C++ class is /// relocatable. /// /// ## Relocatable classes /// /// In order to be able to we wrapped the C++ class must be relocatable. That means /// that it can be moved in memory using `memcpy`. This restriction exists because /// safe Rust is allowed to move your types around. /// /// Most C++ types which do not contain self-references will be compatible, /// although this property cannot be statically checked by `rust-cpp`. /// All types that satisfy `std::is_trivially_copyable` are compatible. /// Maybe future version of the C++ standard would allow a comile-time check: /// [P1144](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1144r4.html) /// /// Unfortunately, as the STL often uses internal self-references for /// optimization purposes, such as the small-string optimization, this disallows /// most std:: classes. /// But `std::unique_ptr` and `std::shared_ptr` works. /// #[macro_export] macro_rules! cpp_class { ($(#[$($attrs:tt)*])* unsafe struct $name:ident as $type:expr) => { $crate::__cpp_class_internal!{@parse [ $(#[$($attrs)*])* ] [] [unsafe struct $name as $type] } }; ($(#[$($attrs:tt)*])* pub unsafe struct $name:ident as $type:expr) => { $crate::__cpp_class_internal!{@parse [ $(#[$($attrs)*])* ] [pub] [unsafe struct $name as $type] } }; ($(#[$($attrs:tt)*])* pub($($pub:tt)*) unsafe struct $name:ident as $type:expr) => { $crate::__cpp_class_internal!{@parse [ $(#[$($attrs)*])* ] [pub($($pub)*)] [unsafe struct $name as $type] } }; } /// Implementation details for cpp_class! #[doc(hidden)] #[macro_export] macro_rules! __cpp_class_internal { (@parse [$($attrs:tt)*] [$($vis:tt)*] [unsafe struct $name:ident as $type:expr]) => { $crate::__cpp_class_internal!{@parse_attributes [ $($attrs)* ] [] [ #[derive($crate::__cpp_internal_class)] #[repr(C)] $($vis)* struct $name { _opaque : [<$name as $crate::CppTrait>::BaseType ; <$name as $crate::CppTrait>::ARRAY_SIZE + (stringify!($($attrs)* $($vis)* unsafe struct $name as $type), 0).1] } ]} }; (@parse_attributes [] [$($attributes:tt)*] [$($result:tt)*]) => ( $($attributes)* $($result)* ); (@parse_attributes [#[derive($($der:ident),*)] $($tail:tt)* ] [$($attributes:tt)*] [$($result:tt)*] ) => ($crate::__cpp_class_internal!{@parse_derive [$($der),*] @parse_attributes [$($tail)*] [ $($attributes)* ] [ $($result)* ] } ); (@parse_attributes [ #[$m:meta] $($tail:tt)* ] [$($attributes:tt)*] [$($result:tt)*]) => ($crate::__cpp_class_internal!{@parse_attributes [$($tail)*] [$($attributes)* #[$m] ] [ $($result)* ] } ); (@parse_derive [] @parse_attributes $($result:tt)*) => ($crate::__cpp_class_internal!{@parse_attributes $($result)*} ); (@parse_derive [PartialEq $(,$tail:ident)*] $($result:tt)*) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] $($result)*} ); (@parse_derive [PartialOrd $(,$tail:ident)*] $($result:tt)*) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] $($result)*} ); (@parse_derive [Ord $(,$tail:ident)*] $($result:tt)*) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] $($result)*} ); (@parse_derive [Default $(,$tail:ident)*] $($result:tt)*) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] $($result)*} ); (@parse_derive [Clone $(,$tail:ident)*] $($result:tt)*) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] $($result)*} ); (@parse_derive [Copy $(,$tail:ident)*] $($result:tt)*) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] $($result)*} ); (@parse_derive [$i:ident $(,$tail:ident)*] @parse_attributes [$($attr:tt)*] [$($attributes:tt)*] [$($result:tt)*] ) => ( $crate::__cpp_class_internal!{@parse_derive [$($tail),*] @parse_attributes [$($attr)*] [$($attributes)* #[derive($i)] ] [ $($result)* ] } ); }