-
Notifications
You must be signed in to change notification settings - Fork 339
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
Support declarative macros inside cxx::bridge #274
Comments
There may be some (potentially convoluted) workaround here which I'm currently attempting to figure out, so if you have any such ideas I'd be very happy to hear them. |
The easiest workaround would be to codegen them from build.rs. // build.rs
use std::env;
use std::fs;
use std::path::Path;
static HANDLE_TYPES: &[&str] = &[
"Handle", "Process", "Thread", "Vmo", "Channel", "Event", "Port",
"Interrupt", "PciDevice", "DebugLog", "Socket", "Resource", "EventPair",
"Job", "Vmar", "Fifo", "Guest", "Vcpu", "Timer", "Iommu", "Bti", "Profile",
"Pmt", "SuspendToken", "Pager", "Exception", "Clock", "Stream",
"MsiAllocation", "MsiInterrupt",
];
fn main() {
let mut bridge = String::new();
bridge += "#[cxx::bridge]\n";
bridge += "pub mod ffi {\n";
for handle_type in HANDLE_TYPES {
bridge += "struct ";
bridge += handle_type;
bridge += " { raw: u32 }\n";
}
bridge += "extern \"C\" {\n";
for handle_type in HANDLE_TYPES {
bridge += "type Cxx";
bridge += handle_type;
bridge += ";\n";
bridge += "type Unowned";
bridge += handle_type;
bridge += ";\n";
bridge += "fn get_handle_";
bridge += &handle_type.to_lowercase();
bridge += "(handle: &Cxx";
bridge += handle_type;
bridge += ") -> u32;\n";
bridge += "fn get_unowned_handle_";
bridge += &handle_type.to_lowercase();
bridge += "(handle: &Unowned";
bridge += handle_type;
bridge += ") -> u32;\n";
}
bridge += "}\n"; // extern "C"
bridge += "}\n"; // mod ffi
let bridge = bridge.as_bytes();
let out_dir = env::var("OUT_DIR").unwrap();
let ref path = Path::new(&out_dir).join("bridge.rs");
fs::write(path, bridge).unwrap();
cxx_build::bridge(path).compile("sbrocket");
} // src/lib.rs
include!(concat!(env!("OUT_DIR"), "/bridge.rs")); |
Our project doesn't support build.rs, but sure, that's a good idea, I can generate the bridge module separately. |
Ok! I'll close the issue since I don't think this is possible to implement otherwise on our end. |
If it's fine with you, can we keep this open as a "blocked feature request"? I realize this isn't possible today - not unless we were to do some crazy things like manually expand the macros similar to how your That "crazy idea" is actually kind of neat the more I think about it, even though it's a hack around proper support for this like that RFC proposes. Inside the bridge proc_macro, we could first send the token stream through rustc again (a la |
It would be useful to be able to use declarative macros inside the bridge. In my use case, I have a large number of formulaic types and methods to declare in the bridge. (The blocks below are untested but should convey the general idea.)
I have 30 such blocks to define, and was actually going to use another declarative macro to invoke the first macro, e.g.:
Obviously this would be/is going to be very tedious to expand manually, never mind that it will be much less maintainable that way.
The text was updated successfully, but these errors were encountered: