1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
//! This crate `cpp` only provides a single macro, the `cpp!` macro. This macro
//! by itself is not useful, but when combined with the `cpp_build` crate it
//! allows embedding 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 <stdint.h>
//!     #include <stdio.h>
//! }}
//! ```
//!
//! 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 = cpp!([y as "int32_t", mut z as "int32_t"] -> i32 as "int32_t" {
//!     z++;
//!     return y + z;
//! });
//! ```
//!
//! # Usage
//!
//! This crate must be used in tandem with the `cpp_build` crate. A basic Cargo
//! project which uses these projects would have a structure like the following:
//!
//! ```text
//! crate
//! |-- Cargo.toml
//! |-- src
//!     |-- lib.rs
//! |-- build.rs
//! ```
//!
//! Where the files look like the following:
//!
//! #### Cargo.toml
//!
//! ```toml
//! [package]
//! build = "build.rs"
//!
//! [dependencies]
//! cpp = "0.3"
//!
//! [build-dependencies]
//! cpp_build = "0.3"
//! ```
//!
//! #### build.rs
//!
//! ```ignore
//! extern crate cpp_build;
//!
//! fn main() {
//!     cpp_build::build("src/lib.rs");
//! }
//! ```
//!
//! #### lib.rs
//!
//! ```ignore
//! #[macro_use]
//! extern crate cpp;
//!
//! cpp!{{
//!     #include <stdio.h>
//! }}
//!
//! fn main() {
//!     unsafe {
//!         cpp!([] {
//!             printf("Hello, World!\n");
//!         });
//!     }
//! }
//! ```

#[macro_use]
#[allow(unused_imports)]
extern crate cpp_macros;
#[doc(hidden)]
pub use cpp_macros::*;

/// This macro is used to embed arbitrary C++ code. See the module level
/// documentation for more details.
#[macro_export]
macro_rules! cpp {
    ({$($body:tt)*}) => { /* Raw text inclusion */ };

    ([$($captures:tt)*] $($rest:tt)*) => {
        {
            #[allow(unused)]
            #[derive(__cpp_internal_closure)]
            enum CppClosureInput {
                Input = (stringify!([$($captures)*] $($rest)*), 0).1
            }
            __cpp_closure_impl![$($captures)*]
        }
    };
}