2个版本
0.1.1 | 2023年8月6日 |
---|---|
0.1.0 | 2023年8月5日 |
#392 in 过程宏
在nucomcore中使用
82KB
2K SLoC
nuidl
nuidl是Nucom的IDL编译器。它既可作为命令行工具,也可作为Rust宏crate提供。
有关Nucom的更多信息,请参阅Nucom 仓库或nucomcore crate (lib.rs crates.io)。
命令行界面
与Nix一起使用
运行 nix shell git +https://git.dblsaiko.net/nucom
以进入带有nuidl的shell。
与Cargo一起使用
运行 cargo install nuidl
以进行安装。
语法
IDL source generator
Usage: nuidl [OPTIONS] <--header|--c-guid|--rust> <FILE>...
Arguments:
<FILE>... Specify input IDL files
Options:
-I, --include <DIR> Add to include path
-c, --header Generate C/C++ header files
-g, --c-guid Generate C GUID source for interfaces
-r, --rust Generate Rust module
-o, --output <DIR> Specify output directory [default: .]
-w, --win32 Generate headers compatible with the Win32 C/C++ API instead of nucom
-h, --help Print help
-V, --version Print version
注释
- 生成的文件依赖于Rust和C/C++的nucomcore库。
- 目前未实现
--win32
选项。
宏crate
nuidl还可以使用过程宏直接从IDL文件生成Rust模块,而无需首先将生成的代码保存到文件中。
将nuidl和nucomcore添加到您的项目中。
[build-dependencies]
nuidl = "0.1.0"
[dependencies]
nucomcore = "0.1.0"
nuidl = "0.1.0"
由于IDL编译器需要访问您在IDL中导入的IDL文件,如iunknown.idl
,因此它需要知道包含路径列表以找到这些文件。在Cargo编译时,这可以自动发现,您只需在build.rs
中运行此代码即可。将以下代码添加到文件中
fn main() {
nuidl::cargo::use_cargo_deps();
}
最后,使用println!("cargo:rustc-env=NUIDL_INCLUDE_PATH={}", paths);
将包含路径传递给nuidl,因此如果您愿意,也可以手动传递这些路径(在这种情况下,您不需要将nuidl作为构建依赖项)。
之后,将您的IDL文件放入crate根目录下的include目录中(建议将其放在子目录中以避免路径冲突,例如Nucom IDLs位于include/nucom)。您可以通过在Cargo.toml中使用package.metadata.nucom.include键来更改crate的include路径。此处指定的路径相对于crate根目录。
[package.metadata.nucom]
include = ["other/path"]
在您的crate中创建一个包含以下内容的idl模块
use nuidl::idl_mod;
// Import everything from each crate's idl module that you want to use. idl_mod!
// generated code will use these.
// You'll probably want nucomcore at the very least.
#[allow(unused_imports)]
use nucomcore::idl::*;
// List your crate's IDL files here, relative to the include directory.
// If your include path is unchanged, this will look in
// include/path/to/foo.idl.
idl_mod!(pub mod "path/to/foo.idl");
idl_mod!(pub mod "path/to/bar.idl");
// If your IDLs have any include statements (not import) referring to C headers,
// they must also be provided as Rust code. For example, a C header baz.h with
// the following contents,
//
// #include <nucom/iunknown.h>
//
// extern IUnknown *make_baz(void);
//
// might be represented as the following module:
pub mod baz {
// The scope module helps to emulate C #include behavior, where including
// a file also brings all the type that file itself includes into scope.
// This is an ugly hack and I might replace it with something else in the
// future. Ideally, everything should be written as IDL definitions anyway,
// so once the IDL compiler is sufficiently done maybe this can go away.
//
// Any declarations visible from the C header (here, IUnknown and make_baz)
// must also be publicly accessible through the scope module.
#[doc(hidden)]
pub mod scope {
// NB: this does not re-export private items from super, like ComPtr.
pub use super::*;
pub use nucomcore::IUnknown;
}
use nucomcore::{ComPtr, IUnknown};
extern "C" {
// ComPtr<T> has the same representation as a T* pointer in C.
pub fn make_baz() -> ComPtr<IUnknown>;
}
}
依赖项
~5–15MB
~176K SLoC