| <!DOCTYPE HTML> |
| <html lang="en" class="sidebar-visible no-js light"> |
| <head> |
| <!-- Book generated using mdBook --> |
| <meta charset="UTF-8"> |
| <title>The bindgen User Guide</title> |
| |
| <meta name="robots" content="noindex" /> |
| |
| |
| |
| |
| <!-- Custom HTML head --> |
| |
| |
| |
| <meta content="text/html; charset=utf-8" http-equiv="Content-Type"> |
| <meta name="description" content="`bindgen` automatically generates Rust FFI bindings to C and C++ libraries."> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <meta name="theme-color" content="#ffffff" /> |
| |
| |
| <link rel="icon" href="favicon.svg"> |
| |
| |
| <link rel="shortcut icon" href="favicon.png"> |
| |
| <link rel="stylesheet" href="css/variables.css"> |
| <link rel="stylesheet" href="css/general.css"> |
| <link rel="stylesheet" href="css/chrome.css"> |
| |
| <link rel="stylesheet" href="css/print.css" media="print"> |
| |
| |
| <!-- Fonts --> |
| <link rel="stylesheet" href="FontAwesome/css/font-awesome.css"> |
| |
| <link rel="stylesheet" href="fonts/fonts.css"> |
| |
| |
| <!-- Highlight.js Stylesheets --> |
| <link rel="stylesheet" href="highlight.css"> |
| <link rel="stylesheet" href="tomorrow-night.css"> |
| <link rel="stylesheet" href="ayu-highlight.css"> |
| |
| <!-- Custom theme stylesheets --> |
| |
| |
| |
| </head> |
| <body> |
| <!-- Provide site root to javascript --> |
| <script type="text/javascript"> |
| var path_to_root = ""; |
| var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light"; |
| </script> |
| |
| <!-- Work around some values being stored in localStorage wrapped in quotes --> |
| <script type="text/javascript"> |
| try { |
| var theme = localStorage.getItem('mdbook-theme'); |
| var sidebar = localStorage.getItem('mdbook-sidebar'); |
| |
| if (theme.startsWith('"') && theme.endsWith('"')) { |
| localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1)); |
| } |
| |
| if (sidebar.startsWith('"') && sidebar.endsWith('"')) { |
| localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1)); |
| } |
| } catch (e) { } |
| </script> |
| |
| <!-- Set the theme before any content is loaded, prevents flash --> |
| <script type="text/javascript"> |
| var theme; |
| try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } |
| if (theme === null || theme === undefined) { theme = default_theme; } |
| var html = document.querySelector('html'); |
| html.classList.remove('no-js') |
| html.classList.remove('light') |
| html.classList.add(theme); |
| html.classList.add('js'); |
| </script> |
| |
| <!-- Hide / unhide sidebar before it is displayed --> |
| <script type="text/javascript"> |
| var html = document.querySelector('html'); |
| var sidebar = 'hidden'; |
| if (document.body.clientWidth >= 1080) { |
| try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { } |
| sidebar = sidebar || 'visible'; |
| } |
| html.classList.remove('sidebar-visible'); |
| html.classList.add("sidebar-" + sidebar); |
| </script> |
| |
| <nav id="sidebar" class="sidebar" aria-label="Table of contents"> |
| <div class="sidebar-scrollbox"> |
| <ol class="chapter"><li class="chapter-item expanded "><a href="introduction.html"><strong aria-hidden="true">1.</strong> Introduction</a></li><li class="chapter-item expanded "><a href="requirements.html"><strong aria-hidden="true">2.</strong> Requirements</a></li><li class="chapter-item expanded "><a href="library-usage.html"><strong aria-hidden="true">3.</strong> Library Usage with build.rs</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="tutorial-0.html"><strong aria-hidden="true">3.1.</strong> Tutorial</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="tutorial-1.html"><strong aria-hidden="true">3.1.1.</strong> Add bindgen as a Build Dependency</a></li><li class="chapter-item expanded "><a href="tutorial-2.html"><strong aria-hidden="true">3.1.2.</strong> Create a wrapper.h Header</a></li><li class="chapter-item expanded "><a href="tutorial-3.html"><strong aria-hidden="true">3.1.3.</strong> Create a build.rs File</a></li><li class="chapter-item expanded "><a href="tutorial-4.html"><strong aria-hidden="true">3.1.4.</strong> Include the Generated Bindings in src/lib.rs</a></li><li class="chapter-item expanded "><a href="tutorial-5.html"><strong aria-hidden="true">3.1.5.</strong> Write a Sanity Test</a></li><li class="chapter-item expanded "><a href="tutorial-6.html"><strong aria-hidden="true">3.1.6.</strong> Publish Your Crate!</a></li></ol></li><li class="chapter-item expanded "><a href="non-system-libraries.html"><strong aria-hidden="true">3.2.</strong> Bindings for non-system libraries</a></li></ol></li><li class="chapter-item expanded "><a href="command-line-usage.html"><strong aria-hidden="true">4.</strong> Command Line Usage</a></li><li class="chapter-item expanded "><a href="customizing-generated-bindings.html"><strong aria-hidden="true">5.</strong> Customizing the Generated Bindings</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="allowlisting.html"><strong aria-hidden="true">5.1.</strong> Allowlisting</a></li><li class="chapter-item expanded "><a href="blocklisting.html"><strong aria-hidden="true">5.2.</strong> Blocklisting</a></li><li class="chapter-item expanded "><a href="opaque.html"><strong aria-hidden="true">5.3.</strong> Treating a Type as an Opaque Blob of Bytes</a></li><li class="chapter-item expanded "><a href="replacing-types.html"><strong aria-hidden="true">5.4.</strong> Replacing One Type with Another</a></li><li class="chapter-item expanded "><a href="nocopy.html"><strong aria-hidden="true">5.5.</strong> Preventing the Derivation of Copy and Clone</a></li><li class="chapter-item expanded "><a href="nodebug.html"><strong aria-hidden="true">5.6.</strong> Preventing the Derivation of Debug</a></li><li class="chapter-item expanded "><a href="nodefault.html"><strong aria-hidden="true">5.7.</strong> Preventing the Derivation of Default</a></li><li class="chapter-item expanded "><a href="must-use-types.html"><strong aria-hidden="true">5.8.</strong> Annotating types with #[must-use]</a></li><li class="chapter-item expanded "><a href="visibility.html"><strong aria-hidden="true">5.9.</strong> Field visibility</a></li><li class="chapter-item expanded "><a href="code-formatting.html"><strong aria-hidden="true">5.10.</strong> Code formatting</a></li></ol></li><li class="chapter-item expanded "><a href="cpp.html"><strong aria-hidden="true">6.</strong> Generating Bindings to C++</a></li><li class="chapter-item expanded "><a href="objc.html"><strong aria-hidden="true">7.</strong> Generating Bindings to Objective-c</a></li><li class="chapter-item expanded "><a href="using-unions.html"><strong aria-hidden="true">8.</strong> Using Unions</a></li><li class="chapter-item expanded "><a href="using-bitfields.html"><strong aria-hidden="true">9.</strong> Using Bitfields</a></li><li class="chapter-item expanded "><a href="using-fam.html"><strong aria-hidden="true">10.</strong> Using Flexible Array Members</a></li><li class="chapter-item expanded "><a href="faq.html"><strong aria-hidden="true">11.</strong> FAQ</a></li></ol> |
| </div> |
| <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div> |
| </nav> |
| |
| <div id="page-wrapper" class="page-wrapper"> |
| |
| <div class="page"> |
| |
| <div id="menu-bar-hover-placeholder"></div> |
| <div id="menu-bar" class="menu-bar sticky bordered"> |
| <div class="left-buttons"> |
| <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar"> |
| <i class="fa fa-bars"></i> |
| </button> |
| <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list"> |
| <i class="fa fa-paint-brush"></i> |
| </button> |
| <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu"> |
| <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li> |
| <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li> |
| </ul> |
| |
| <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar"> |
| <i class="fa fa-search"></i> |
| </button> |
| |
| </div> |
| |
| <h1 class="menu-title">The bindgen User Guide</h1> |
| |
| <div class="right-buttons"> |
| |
| <a href="print.html" title="Print this book" aria-label="Print this book"> |
| <i id="print-button" class="fa fa-print"></i> |
| </a> |
| |
| |
| <a href="https://github.com/rust-lang/rust-bindgen" title="Git repository" aria-label="Git repository"> |
| <i id="git-repository-button" class="fa fa-github"></i> |
| </a> |
| |
| </div> |
| </div> |
| |
| |
| <div id="search-wrapper" class="hidden"> |
| <form id="searchbar-outer" class="searchbar-outer"> |
| <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header"> |
| </form> |
| <div id="searchresults-outer" class="searchresults-outer hidden"> |
| <div id="searchresults-header" class="searchresults-header"></div> |
| <ul id="searchresults"> |
| </ul> |
| </div> |
| </div> |
| |
| |
| <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM --> |
| <script type="text/javascript"> |
| document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible'); |
| document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible'); |
| Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) { |
| link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1); |
| }); |
| </script> |
| |
| <div id="content" class="content"> |
| <main> |
| <h1><a class="header" href="#introduction" id="introduction">Introduction</a></h1> |
| <p><strong><a href="https://github.com/rust-lang/rust-bindgen"><code>bindgen</code></a> automatically generates Rust |
| FFI bindings to C and C++ libraries.</strong></p> |
| <p>For example, given the C header <code>cool.h</code>:</p> |
| <pre><code class="language-c">typedef struct CoolStruct { |
| int x; |
| int y; |
| } CoolStruct; |
| |
| void cool_function(int i, char c, CoolStruct* cs); |
| </code></pre> |
| <p><code>bindgen</code> produces Rust FFI code allowing you to call into the <code>cool</code> library's |
| functions and use its types:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>/* automatically generated by rust-bindgen 0.99.9 */ |
| |
| #[repr(C)] |
| pub struct CoolStruct { |
| pub x: ::std::os::raw::c_int, |
| pub y: ::std::os::raw::c_int, |
| } |
| |
| extern "C" { |
| pub fn cool_function(i: ::std::os::raw::c_int, |
| c: ::std::os::raw::c_char, |
| cs: *mut CoolStruct); |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <h1><a class="header" href="#requirements" id="requirements">Requirements</a></h1> |
| <p>This page lists the requirements for running <code>bindgen</code> and how to get them.</p> |
| <h2><a class="header" href="#clang" id="clang">Clang</a></h2> |
| <p><code>bindgen</code> leverages <code>libclang</code> to preprocess, parse, and type check C and C++ |
| header files.</p> |
| <p>It is required to use Clang 5.0 or greater.</p> |
| <h3><a class="header" href="#installing-clang" id="installing-clang">Installing Clang</a></h3> |
| <h4><a class="header" href="#windows" id="windows">Windows</a></h4> |
| <p>If you use winget:</p> |
| <pre><code class="language-powershell">winget install LLVM.LLVM |
| </code></pre> |
| <p>Alternatively, you can download and install the official pre-built binary from |
| <a href="http://releases.llvm.org/download.html">LLVM download page</a>.</p> |
| <p>You will also need to set <code>LIBCLANG_PATH</code> as an <a href="https://www.techjunkie.com/environment-variables-windows-10/">environment |
| variable</a> pointing |
| to the <code>bin</code> directory of your LLVM install. For example, if you installed LLVM |
| to <code>D:\programs\LLVM</code>, then you'd set the value to be <code>D:\programs\LLVM\bin</code>.</p> |
| <p>Alternatively, for Mingw64, you can install clang via</p> |
| <pre><code class="language-bash">pacman -S mingw64/mingw-w64-x86_64-clang |
| </code></pre> |
| <h4><a class="header" href="#macos" id="macos">macOS</a></h4> |
| <p>If you use Homebrew:</p> |
| <pre><code class="language-bash">$ brew install llvm |
| </code></pre> |
| <p>If you use MacPorts:</p> |
| <pre><code class="language-bash">$ port install clang |
| </code></pre> |
| <h4><a class="header" href="#debian-based-linuxes" id="debian-based-linuxes">Debian-based Linuxes</a></h4> |
| <pre><code class="language-bash"># apt install llvm-dev libclang-dev clang |
| </code></pre> |
| <p>Ubuntu 18.04 provides the necessary packages directly.</p> |
| <h4><a class="header" href="#arch" id="arch">Arch</a></h4> |
| <pre><code class="language-bash"># pacman -S clang |
| </code></pre> |
| <h4><a class="header" href="#fedora" id="fedora">Fedora</a></h4> |
| <pre><code class="language-bash"># dnf install clang-devel |
| </code></pre> |
| <h4><a class="header" href="#openbsd" id="openbsd">OpenBSD</a></h4> |
| <pre><code class="language-bash"># pkg_add llvm |
| </code></pre> |
| <p>Add <code>export LIBCLANG_PATH=/usr/local/lib</code> to your profile.</p> |
| <h4><a class="header" href="#from-source" id="from-source">From source</a></h4> |
| <p>If your package manager doesn't yet offer Clang 5.0, you'll need to build from |
| source. For that, follow the |
| instructions <a href="http://clang.llvm.org/get_started.html">here</a>.</p> |
| <p>Those instructions list optional steps. For <code>bindgen</code>:</p> |
| <ul> |
| <li>Checkout and build clang</li> |
| <li>Checkout and build the extra-clang-tools</li> |
| <li>You do not need to checkout or build compiler-rt</li> |
| <li>You do not need to checkout or build libcxx</li> |
| </ul> |
| <h1><a class="header" href="#library-usage-with-buildrs" id="library-usage-with-buildrs">Library Usage with <code>build.rs</code></a></h1> |
| <p>💡 This is the recommended way to use <code>bindgen</code>. 💡</p> |
| <p>Often times C and C++ headers will have platform- and architecture-specific |
| <code>#ifdef</code>s that affect the shape of the Rust FFI bindings we need to create to |
| interface Rust code with the outside world. By using <code>bindgen</code> as a library |
| inside your <code>build.rs</code>, you can generate bindings for the current target |
| on-the-fly. Otherwise, you would need to generate and maintain |
| <code>x86_64-unknown-linux-gnu-bindings.rs</code>, <code>x86_64-apple-darwin-bindings.rs</code>, |
| etc... separate bindings files for each of your supported targets, which can be |
| a huge pain. The downside is that everyone building your crate also needs |
| <code>libclang</code> available to run <code>bindgen</code>.</p> |
| <h2><a class="header" href="#library-api-documentation" id="library-api-documentation">Library API Documentation</a></h2> |
| <p><a href="https://docs.rs/bindgen">📚 There is complete API reference documentation on docs.rs 📚</a></p> |
| <h2><a class="header" href="#tutorial" id="tutorial">Tutorial</a></h2> |
| <p>The next section contains a detailed, step-by-step tutorial for using <code>bindgen</code> |
| as a library inside <code>build.rs</code>.</p> |
| <h1><a class="header" href="#tutorial-1" id="tutorial-1">Tutorial</a></h1> |
| <p>The following tutorial is adapted from <a href="http://fitzgeraldnick.com/2016/12/14/using-libbindgen-in-build-rs.html">this blog post</a>.</p> |
| <p>What follows is a whirlwind introductory tutorial to using <code>bindgen</code> from inside |
| <code>build.rs</code>. We'll generate bindings to <code>bzip2</code> (which is available on most |
| systems) on-the-fly.</p> |
| <p><a href="https://github.com/fitzgen/bindgen-tutorial-bzip2-sys"><strong>TL;DR?</strong> The full tutorial code is available here.</a></p> |
| <h1><a class="header" href="#add-bindgen-as-a-build-dependency" id="add-bindgen-as-a-build-dependency">Add <code>bindgen</code> as a Build Dependency</a></h1> |
| <p>First we need to declare a build-time dependency on <code>bindgen</code> by adding it to |
| the <code>[build-dependencies]</code> section of our crate's <code>Cargo.toml</code> file.</p> |
| <p>Please always use the latest version of <code>bindgen</code>, as it has the most fixes and |
| best compatibility. |
| You can always check the latest version at |
| <a href="https://crates.io/crates/bindgen">the bindgen page in crates.io</a>.</p> |
| <pre><code class="language-toml">[build-dependencies] |
| bindgen = "0.65.1" |
| </code></pre> |
| <blockquote> |
| <p>⚠️ <strong>Warning</strong></p> |
| <p><code>bindgen</code> needs to be added to the <code>[build-dependencies]</code> section, not the normal |
| <code>[dependencies]</code> section. If you add it as a regular dependency, you will get |
| errors like the following: <code>error[E0463]: can't find crate for `bindgen`</code></p> |
| </blockquote> |
| <h1><a class="header" href="#create-a-wrapperh-header" id="create-a-wrapperh-header">Create a <code>wrapper.h</code> Header</a></h1> |
| <p>The <code>wrapper.h</code> file will include all the various headers containing |
| declarations of structs and functions we would like bindings for. In the |
| particular case of <code>bzip2</code>, this is pretty easy since the entire public API is |
| contained in a single header. For a project like <a href="https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/How_to_embed_the_JavaScript_engine">SpiderMonkey</a>, |
| where the public API is split across multiple header files and grouped by |
| functionality, we'd want to include all those headers we want to bind to in this |
| single <code>wrapper.h</code> entry point for <code>bindgen</code>.</p> |
| <p>Here is our <code>wrapper.h</code>:</p> |
| <pre><code class="language-c">#include <bzlib.h> |
| </code></pre> |
| <p>This is also where we would add any <a href="./replacing-types.html">replacement types</a>, |
| if we were using some.</p> |
| <h1><a class="header" href="#create-a-buildrs-file" id="create-a-buildrs-file">Create a <code>build.rs</code> File</a></h1> |
| <p>We create a <code>build.rs</code> file in our crate's root. Cargo will pick up on the existence of this file, then compile and execute it before the rest of the crate is built. |
| This can be used to generate code at compile time. |
| And of course in our case, we will be generating Rust FFI |
| bindings to <code>bzip2</code> at compile time. The resulting bindings will be written to |
| <code>$OUT_DIR/bindings.rs</code> where <code>$OUT_DIR</code> is chosen by <code>cargo</code> and is something |
| like <code>./target/debug/build/bindgen-tutorial-bzip2-sys-afc7747d7eafd720/out/</code>.</p> |
| <p>Note that the associated shared object to <code>bz2</code> is <code>libbz2.so</code>. In general, a <code>lib<name>.so</code> should be referenced in the build file by <code><name></code>.</p> |
| <pre><code class="language-rust ignore">use std::env; |
| use std::path::PathBuf; |
| |
| fn main() { |
| // Tell cargo to look for shared libraries in the specified directory |
| println!("cargo:rustc-link-search=/path/to/lib"); |
| |
| // Tell cargo to tell rustc to link the system bzip2 |
| // shared library. |
| println!("cargo:rustc-link-lib=bz2"); |
| |
| // The bindgen::Builder is the main entry point |
| // to bindgen, and lets you build up options for |
| // the resulting bindings. |
| let bindings = bindgen::Builder::default() |
| // The input header we would like to generate |
| // bindings for. |
| .header("wrapper.h") |
| // Tell cargo to invalidate the built crate whenever any of the |
| // included header files changed. |
| .parse_callbacks(Box::new(bindgen::CargoCallbacks::new())) |
| // Finish the builder and generate the bindings. |
| .generate() |
| // Unwrap the Result and panic on failure. |
| .expect("Unable to generate bindings"); |
| |
| // Write the bindings to the $OUT_DIR/bindings.rs file. |
| let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); |
| bindings |
| .write_to_file(out_path.join("bindings.rs")) |
| .expect("Couldn't write bindings!"); |
| } |
| </code></pre> |
| <p>Now, when we run <code>cargo build</code>, our bindings to <code>bzip2</code> are generated on the |
| fly!</p> |
| <p><a href="https://doc.rust-lang.org/cargo/reference/build-scripts.html">There's more info about <code>build.rs</code> files in the Cargo documentation.</a></p> |
| <h1><a class="header" href="#include-the-generated-bindings-in-srclibrs" id="include-the-generated-bindings-in-srclibrs">Include the Generated Bindings in <code>src/lib.rs</code></a></h1> |
| <p>We can use the <code>include!</code> macro to dump our generated bindings right into our |
| crate's main entry point, <code>src/lib.rs</code>:</p> |
| <pre><code class="language-rust ignore">#![allow(non_upper_case_globals)] |
| #![allow(non_camel_case_types)] |
| #![allow(non_snake_case)] |
| |
| include!(concat!(env!("OUT_DIR"), "/bindings.rs")); |
| </code></pre> |
| <p>Because <code>bzip2</code>'s symbols do not follow Rust's style conventions, we suppress a |
| bunch of warnings with a few <code>#![allow(...)]</code> pragmas.</p> |
| <p>We can run <code>cargo build</code> again to check that the bindings themselves compile:</p> |
| <pre><code class="language-bash">$ cargo build |
| Compiling bindgen-tutorial-bzip2-sys v0.1.0 |
| Finished debug [unoptimized + debuginfo] target(s) in 62.8 secs |
| </code></pre> |
| <p>And we can run <code>cargo test</code> to verify that the layout, size, and alignment of |
| our generated Rust FFI structs match what <code>bindgen</code> thinks they should be:</p> |
| <pre><code class="language-bash">$ cargo test |
| Compiling bindgen-tutorial-bzip2-sys v0.1.0 |
| Finished debug [unoptimized + debuginfo] target(s) in 0.0 secs |
| Running target/debug/deps/bzip2_sys-10413fc2af207810 |
| |
| running 14 tests |
| test bindgen_test_layout___darwin_pthread_handler_rec ... ok |
| test bindgen_test_layout___sFILE ... ok |
| test bindgen_test_layout___sbuf ... ok |
| test bindgen_test_layout__bindgen_ty_1 ... ok |
| test bindgen_test_layout__bindgen_ty_2 ... ok |
| test bindgen_test_layout__opaque_pthread_attr_t ... ok |
| test bindgen_test_layout__opaque_pthread_cond_t ... ok |
| test bindgen_test_layout__opaque_pthread_mutex_t ... ok |
| test bindgen_test_layout__opaque_pthread_condattr_t ... ok |
| test bindgen_test_layout__opaque_pthread_mutexattr_t ... ok |
| test bindgen_test_layout__opaque_pthread_once_t ... ok |
| test bindgen_test_layout__opaque_pthread_rwlock_t ... ok |
| test bindgen_test_layout__opaque_pthread_rwlockattr_t ... ok |
| test bindgen_test_layout__opaque_pthread_t ... ok |
| |
| test result: ok. 14 passed; 0 failed; 0 ignored; 0 measured |
| |
| Doc-tests bindgen-tutorial-bzip2-sys |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured |
| </code></pre> |
| <h1><a class="header" href="#write-a-sanity-test" id="write-a-sanity-test">Write a Sanity Test</a></h1> |
| <p>Finally, to tie everything together, let's write a sanity test that round trips |
| some text through compression and decompression, and then asserts that it came |
| back out the same as it went in. This is a little wordy using the raw FFI |
| bindings, but hopefully we wouldn't usually ask people to do this, we'd provide |
| a nice Rust-y API on top of the raw FFI bindings for them. However, since this |
| is for testing the bindings directly, our sanity test will use the bindings |
| directly.</p> |
| <p>The test data I'm round tripping are some Futurama quotes I got off the internet |
| and put in the <code>futurama-quotes.txt</code> file, which is read into a <code>&'static str</code> |
| at compile time via the <code>include_str!("../futurama-quotes.txt")</code> macro |
| invocation.</p> |
| <p>Without further ado, here is the test, which should be appended to the bottom of |
| our <code>src/lib.rs</code> file:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span>#[cfg(test)] |
| mod tests { |
| use super::*; |
| use std::mem; |
| |
| #[test] |
| fn round_trip_compression_decompression() { |
| unsafe { |
| let input = include_str!("../futurama-quotes.txt").as_bytes(); |
| let mut compressed_output: Vec<u8> = vec![0; input.len()]; |
| let mut decompressed_output: Vec<u8> = vec![0; input.len()]; |
| |
| // Construct a compression stream. |
| let mut stream: bz_stream = mem::zeroed(); |
| let result = BZ2_bzCompressInit(&mut stream as *mut _, |
| 1, // 1 x 100000 block size |
| 4, // verbosity (4 = most verbose) |
| 0); // default work factor |
| match result { |
| r if r == (BZ_CONFIG_ERROR as _) => panic!("BZ_CONFIG_ERROR"), |
| r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), |
| r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), |
| r if r == (BZ_OK as _) => {}, |
| r => panic!("Unknown return value = {}", r), |
| } |
| |
| // Compress `input` into `compressed_output`. |
| stream.next_in = input.as_ptr() as *mut _; |
| stream.avail_in = input.len() as _; |
| stream.next_out = compressed_output.as_mut_ptr() as *mut _; |
| stream.avail_out = compressed_output.len() as _; |
| let result = BZ2_bzCompress(&mut stream as *mut _, BZ_FINISH as _); |
| match result { |
| r if r == (BZ_RUN_OK as _) => panic!("BZ_RUN_OK"), |
| r if r == (BZ_FLUSH_OK as _) => panic!("BZ_FLUSH_OK"), |
| r if r == (BZ_FINISH_OK as _) => panic!("BZ_FINISH_OK"), |
| r if r == (BZ_SEQUENCE_ERROR as _) => panic!("BZ_SEQUENCE_ERROR"), |
| r if r == (BZ_STREAM_END as _) => {}, |
| r => panic!("Unknown return value = {}", r), |
| } |
| |
| // Finish the compression stream. |
| let result = BZ2_bzCompressEnd(&mut stream as *mut _); |
| match result { |
| r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), |
| r if r == (BZ_OK as _) => {}, |
| r => panic!("Unknown return value = {}", r), |
| } |
| |
| // Construct a decompression stream. |
| let mut stream: bz_stream = mem::zeroed(); |
| let result = BZ2_bzDecompressInit(&mut stream as *mut _, |
| 4, // verbosity (4 = most verbose) |
| 0); // default small factor |
| match result { |
| r if r == (BZ_CONFIG_ERROR as _) => panic!("BZ_CONFIG_ERROR"), |
| r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), |
| r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), |
| r if r == (BZ_OK as _) => {}, |
| r => panic!("Unknown return value = {}", r), |
| } |
| |
| // Decompress `compressed_output` into `decompressed_output`. |
| stream.next_in = compressed_output.as_ptr() as *mut _; |
| stream.avail_in = compressed_output.len() as _; |
| stream.next_out = decompressed_output.as_mut_ptr() as *mut _; |
| stream.avail_out = decompressed_output.len() as _; |
| let result = BZ2_bzDecompress(&mut stream as *mut _); |
| match result { |
| r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), |
| r if r == (BZ_DATA_ERROR as _) => panic!("BZ_DATA_ERROR"), |
| r if r == (BZ_DATA_ERROR_MAGIC as _) => panic!("BZ_DATA_ERROR"), |
| r if r == (BZ_MEM_ERROR as _) => panic!("BZ_MEM_ERROR"), |
| r if r == (BZ_OK as _) => panic!("BZ_OK"), |
| r if r == (BZ_STREAM_END as _) => {}, |
| r => panic!("Unknown return value = {}", r), |
| } |
| |
| // Close the decompression stream. |
| let result = BZ2_bzDecompressEnd(&mut stream as *mut _); |
| match result { |
| r if r == (BZ_PARAM_ERROR as _) => panic!("BZ_PARAM_ERROR"), |
| r if r == (BZ_OK as _) => {}, |
| r => panic!("Unknown return value = {}", r), |
| } |
| |
| assert_eq!(input, &decompressed_output[..]); |
| } |
| } |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <p>Now let's run <code>cargo test</code> again and verify that everything is linking and binding |
| properly!</p> |
| <pre><code class="language-bash">$ cargo test |
| Compiling bindgen-tutorial-bzip2-sys v0.1.0 |
| Finished debug [unoptimized + debuginfo] target(s) in 0.54 secs |
| Running target/debug/deps/bindgen_tutorial_bzip2_sys-1c5626bbc4401c3a |
| |
| running 15 tests |
| test bindgen_test_layout___darwin_pthread_handler_rec ... ok |
| test bindgen_test_layout___sFILE ... ok |
| test bindgen_test_layout___sbuf ... ok |
| test bindgen_test_layout__bindgen_ty_1 ... ok |
| test bindgen_test_layout__bindgen_ty_2 ... ok |
| test bindgen_test_layout__opaque_pthread_attr_t ... ok |
| test bindgen_test_layout__opaque_pthread_cond_t ... ok |
| test bindgen_test_layout__opaque_pthread_condattr_t ... ok |
| test bindgen_test_layout__opaque_pthread_mutex_t ... ok |
| test bindgen_test_layout__opaque_pthread_mutexattr_t ... ok |
| test bindgen_test_layout__opaque_pthread_once_t ... ok |
| test bindgen_test_layout__opaque_pthread_rwlock_t ... ok |
| test bindgen_test_layout__opaque_pthread_rwlockattr_t ... ok |
| test bindgen_test_layout__opaque_pthread_t ... ok |
| block 1: crc = 0x47bfca17, combined CRC = 0x47bfca17, size = 2857 |
| bucket sorting ... |
| depth 1 has 2849 unresolved strings |
| depth 2 has 2702 unresolved strings |
| depth 4 has 1508 unresolved strings |
| depth 8 has 538 unresolved strings |
| depth 16 has 148 unresolved strings |
| depth 32 has 0 unresolved strings |
| reconstructing block ... |
| 2857 in block, 2221 after MTF & 1-2 coding, 61+2 syms in use |
| initial group 5, [0 .. 1], has 570 syms (25.7%) |
| initial group 4, [2 .. 2], has 256 syms (11.5%) |
| initial group 3, [3 .. 6], has 554 syms (24.9%) |
| initial group 2, [7 .. 12], has 372 syms (16.7%) |
| initial group 1, [13 .. 62], has 469 syms (21.1%) |
| pass 1: size is 2743, grp uses are 13 6 15 0 11 |
| pass 2: size is 1216, grp uses are 13 7 15 0 10 |
| pass 3: size is 1214, grp uses are 13 8 14 0 10 |
| pass 4: size is 1213, grp uses are 13 9 13 0 10 |
| bytes: mapping 19, selectors 17, code lengths 79, codes 1213 |
| final combined CRC = 0x47bfca17 |
| |
| [1: huff+mtf rt+rld {0x47bfca17, 0x47bfca17}] |
| combined CRCs: stored = 0x47bfca17, computed = 0x47bfca17 |
| test tests::round_trip_compression_decompression ... ok |
| |
| test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured |
| |
| Doc-tests bindgen-tutorial-bzip2-sys |
| |
| running 0 tests |
| |
| test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured |
| </code></pre> |
| <h1><a class="header" href="#publish-your-crate" id="publish-your-crate">Publish Your Crate!</a></h1> |
| <p>That's it! Now we can publish our crate on crates.io and we can write a nice, |
| Rust-y API wrapping the raw FFI bindings in a safe interface. However, there is |
| already a <a href="https://crates.io/crates/bzip2-sys"><code>bzip2-sys</code></a> crate providing raw FFI bindings, and there is |
| already a <a href="https://crates.io/crates/bzip2"><code>bzip2</code></a> crate providing a nice, safe, Rust-y API on top of the |
| bindings, so we have nothing left to do here!</p> |
| <p>Check out the <a href="https://github.com/fitzgen/bindgen-tutorial-bzip2-sys">full code on Github!</a></p> |
| <p>Now let's suppose we want to generate bindings for a non-system library. We |
| will be the same crate setup as the previous tutorial. First let's create a new |
| directory <code>hello</code> with two files inside it. A C source file <code>hello.c</code> |
| containing</p> |
| <pre><code class="language-c">int hello() { |
| return 42; |
| } |
| </code></pre> |
| <p>and a C header file <code>hello.h</code> containing</p> |
| <pre><code class="language-c">int hello(); |
| </code></pre> |
| <p>Given that the library has not been compiled yet, we need to modify the |
| <code>build.rs</code> build script to compile the <code>hello.c</code> source file into a static |
| library:</p> |
| <pre><code class="language-rust ignore">use std::env; |
| use std::path::PathBuf; |
| |
| use bindgen::CargoCallbacks; |
| |
| fn main() { |
| // This is the directory where the `c` library is located. |
| let libdir_path = PathBuf::from("hello") |
| // Canonicalize the path as `rustc-link-search` requires an absolute |
| // path. |
| .canonicalize() |
| .expect("cannot canonicalize path"); |
| |
| // This is the path to the `c` headers file. |
| let headers_path = libdir_path.join("hello.h"); |
| let headers_path_str = headers_path.to_str().expect("Path is not a valid string"); |
| |
| // This is the path to the intermediate object file for our library. |
| let obj_path = libdir_path.join("hello.o"); |
| // This is the path to the static library file. |
| let lib_path = libdir_path.join("libhello.a"); |
| |
| // Tell cargo to look for shared libraries in the specified directory |
| println!("cargo:rustc-link-search={}", libdir_path.to_str().unwrap()); |
| |
| // Tell cargo to tell rustc to link our `hello` library. Cargo will |
| // automatically know it must look for a `libhello.a` file. |
| println!("cargo:rustc-link-lib=hello"); |
| |
| // Run `clang` to compile the `hello.c` file into a `hello.o` object file. |
| // Unwrap if it is not possible to spawn the process. |
| if !std::process::Command::new("clang") |
| .arg("-c") |
| .arg("-o") |
| .arg(&obj_path) |
| .arg(libdir_path.join("hello.c")) |
| .output() |
| .expect("could not spawn `clang`") |
| .status |
| .success() |
| { |
| // Panic if the command was not successful. |
| panic!("could not compile object file"); |
| } |
| |
| // Run `ar` to generate the `libhello.a` file from the `hello.o` file. |
| // Unwrap if it is not possible to spawn the process. |
| if !std::process::Command::new("ar") |
| .arg("rcs") |
| .arg(lib_path) |
| .arg(obj_path) |
| .output() |
| .expect("could not spawn `ar`") |
| .status |
| .success() |
| { |
| // Panic if the command was not successful. |
| panic!("could not emit library file"); |
| } |
| |
| // The bindgen::Builder is the main entry point |
| // to bindgen, and lets you build up options for |
| // the resulting bindings. |
| let bindings = bindgen::Builder::default() |
| // The input header we would like to generate |
| // bindings for. |
| .header(headers_path_str) |
| // Tell cargo to invalidate the built crate whenever any of the |
| // included header files changed. |
| .parse_callbacks(Box::new(CargoCallbacks::new())) |
| // Finish the builder and generate the bindings. |
| .generate() |
| // Unwrap the Result and panic on failure. |
| .expect("Unable to generate bindings"); |
| |
| // Write the bindings to the $OUT_DIR/bindings.rs file. |
| let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()).join("bindings.rs"); |
| bindings |
| .write_to_file(out_path) |
| .expect("Couldn't write bindings!"); |
| } |
| </code></pre> |
| <h1><a class="header" href="#command-line-usage" id="command-line-usage">Command Line Usage</a></h1> |
| <p>Install the <code>bindgen</code> executable with <code>cargo</code>:</p> |
| <pre><code class="language-bash">$ cargo install bindgen-cli |
| </code></pre> |
| <p>The <code>bindgen</code> executable is installed to <code>~/.cargo/bin</code>. You have to add that |
| directory to your <code>$PATH</code> to use <code>bindgen</code>.</p> |
| <p><code>bindgen</code> takes the path to an input C or C++ header file, and optionally an |
| output file path for the generated bindings. If the output file path is not |
| supplied, the bindings are printed to <code>stdout</code>.</p> |
| <p>If we wanted to generated Rust FFI bindings from a C header named <code>input.h</code> and |
| put them in the <code>bindings.rs</code> file, we would invoke <code>bindgen</code> like this:</p> |
| <pre><code class="language-bash">$ bindgen input.h -o bindings.rs |
| </code></pre> |
| <p>For more details, pass the <code>--help</code> flag:</p> |
| <pre><code class="language-bash">$ bindgen --help |
| </code></pre> |
| <h1><a class="header" href="#customizing-the-generated-bindings" id="customizing-the-generated-bindings">Customizing the Generated Bindings</a></h1> |
| <p>The translation of classes, structs, enums, and typedefs can be adjusted in a |
| few ways:</p> |
| <ol> |
| <li> |
| <p>By using the <code>bindgen::Builder</code>'s configuration methods, when using <code>bindgen</code> |
| as a library.</p> |
| </li> |
| <li> |
| <p>By passing extra flags and options to the <code>bindgen</code> executable.</p> |
| </li> |
| <li> |
| <p>By adding an annotation comment to the C/C++ source code. Annotations are |
| specially formatted HTML tags inside doxygen style comments:</p> |
| <ul> |
| <li> |
| <p>For single line comments:</p> |
| <pre><code class="language-c">/// <div rustbindgen></div> |
| </code></pre> |
| </li> |
| <li> |
| <p>For multi-line comments:</p> |
| <pre><code class="language-c">/** |
| * <div rustbindgen></div> |
| */ |
| </code></pre> |
| </li> |
| </ul> |
| </li> |
| </ol> |
| <p>We'll leave the nitty-gritty details to |
| the <a href="https://docs.rs/bindgen">docs.rs API reference</a> and <code>bindgen --help</code>, but |
| provide higher level concept documentation here.</p> |
| <h1><a class="header" href="#allowlisting" id="allowlisting">Allowlisting</a></h1> |
| <p>Allowlisting allows us to be precise about which type, function, and global |
| variable definitions <code>bindgen</code> generates bindings for. By default, if we don't |
| specify any allowlisting rules, everything is considered allowlisted. This may |
| not be desirable because of either</p> |
| <ul> |
| <li>the generated bindings contain a lot of extra definitions we don't plan on using, or</li> |
| <li>the header file contains C++ features for which Rust does not have a |
| corresponding form (such as partial template specialization), and we would |
| like to avoid these definitions</li> |
| </ul> |
| <p>If we specify allowlisting rules, then <code>bindgen</code> will only generate bindings to |
| types, functions, and global variables that match the allowlisting rules, or are |
| transitively used by a definition that matches them.</p> |
| <h3><a class="header" href="#library" id="library">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_type"><code>bindgen::Builder::allowlist_type</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_function"><code>bindgen::Builder::allowlist_function</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_var"><code>bindgen::Builder::allowlist_var</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_file"><code>bindgen::Builder::allowlist_file</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.allowlist_item"><code>bindgen::Builder::allowlist_item</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line" id="command-line">Command Line</a></h3> |
| <ul> |
| <li><code>--allowlist-type <type></code></li> |
| <li><code>--allowlist-function <function></code></li> |
| <li><code>--allowlist-var <var></code></li> |
| <li><code>--allowlist-file <path></code></li> |
| <li><code>--allowlist-item <item></code></li> |
| </ul> |
| <h3><a class="header" href="#annotations" id="annotations">Annotations</a></h3> |
| <p>None.</p> |
| <h1><a class="header" href="#blocklisting" id="blocklisting">Blocklisting</a></h1> |
| <p>If you need to provide your own custom translation of some type (for example, |
| because you need to wrap one of its fields in an <code>UnsafeCell</code>), you can |
| explicitly blocklist generation of its definition. Uses of the blocklisted type |
| will still appear in other types' definitions. (If you don't want the type to |
| appear in the bindings at |
| all, <a href="./opaque.html">make it opaque</a> instead of |
| blocklisting it.)</p> |
| <p>Blocklisted types are pessimistically assumed not to be able to <code>derive</code> any |
| traits, which can transitively affect other types' ability to <code>derive</code> traits or |
| not.</p> |
| <p>The <code>blocklist-file</code> option also allows the blocklisting of all items from a |
| particular path regex, for example to block all types defined in system headers |
| that are transitively included.</p> |
| <h3><a class="header" href="#library-1" id="library-1">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_file"><code>bindgen::Builder::blocklist_file</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_function"><code>bindgen::Builder::blocklist_function</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_item"><code>bindgen::Builder::blocklist_item</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_type"><code>bindgen::Builder::blocklist_type</code></a></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.blocklist_var"><code>bindgen::Builder::blocklist_var</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-1" id="command-line-1">Command Line</a></h3> |
| <ul> |
| <li><code>--blocklist-file <path></code></li> |
| <li><code>--blocklist-function <function></code></li> |
| <li><code>--blocklist-item <item></code></li> |
| <li><code>--blocklist-type <type></code></li> |
| <li><code>--blocklist-var <var></code></li> |
| </ul> |
| <h3><a class="header" href="#annotations-1" id="annotations-1">Annotations</a></h3> |
| <pre><code class="language-cpp">/// <div rustbindgen hide></div> |
| class Foo { |
| // ... |
| }; |
| </code></pre> |
| <h1><a class="header" href="#treating-a-type-as-an-opaque-blob-of-bytes" id="treating-a-type-as-an-opaque-blob-of-bytes">Treating a Type as an Opaque Blob of Bytes</a></h1> |
| <p>Sometimes a type definition is simply not translatable to Rust, for example it |
| uses |
| <a href="https://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error">C++'s SFINAE</a> for |
| which Rust has no equivalent. In these cases, it is best to treat all |
| occurrences of the type as an opaque blob of bytes with a size and |
| alignment. <code>bindgen</code> will attempt to detect such cases and do this |
| automatically, but other times it needs some explicit help from you.</p> |
| <h3><a class="header" href="#library-2" id="library-2">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.opaque_type"><code>bindgen::Builder::opaque_type</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-2" id="command-line-2">Command Line</a></h3> |
| <ul> |
| <li><code>--opaque-type <type></code></li> |
| </ul> |
| <h3><a class="header" href="#annotation" id="annotation">Annotation</a></h3> |
| <pre><code class="language-cpp">/// <div rustbindgen opaque></div> |
| class Foo { |
| // ... |
| }; |
| </code></pre> |
| <h1><a class="header" href="#replacing-one-type-with-another" id="replacing-one-type-with-another">Replacing One Type with Another</a></h1> |
| <p>The <code>replaces</code> annotation can be used to use a type as a replacement for other |
| (presumably more complex) type. This is used in Stylo to generate bindings for |
| structures that for multiple reasons are too complex for bindgen to understand.</p> |
| <p>For example, in a C++ header:</p> |
| <pre><code class="language-cpp">/** |
| * <div rustbindgen replaces="nsTArray"></div> |
| */ |
| template<typename T> |
| class nsTArray_Simple { |
| T* mBuffer; |
| public: |
| // The existence of a destructor here prevents bindgen from deriving the Clone |
| // trait via a simple memory copy. |
| ~nsTArray_Simple() {}; |
| }; |
| </code></pre> |
| <p>That way, after code generation, the bindings for the <code>nsTArray</code> type are |
| the ones that would be generated for <code>nsTArray_Simple</code>.</p> |
| <p>Replacing is only available as an annotation. To replace a C or C++ definition |
| with a Rust definition, use <a href="./blocklisting.html">blocklisting</a>.</p> |
| <h1><a class="header" href="#preventing-the-derivation-of-copy-and-clone" id="preventing-the-derivation-of-copy-and-clone">Preventing the Derivation of <code>Copy</code> and <code>Clone</code></a></h1> |
| <p><code>bindgen</code> will attempt to derive the <code>Copy</code> and <code>Clone</code> traits on a best-effort |
| basis. Sometimes, it might not understand that although adding <code>#[derive(Copy, Clone)]</code> to a translated type definition will compile, it still shouldn't do |
| that for reasons it can't know. In these cases, the <code>nocopy</code> annotation can be |
| used to prevent bindgen to autoderive the <code>Copy</code> and <code>Clone</code> traits for a type.</p> |
| <h3><a class="header" href="#library-3" id="library-3">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_copy"><code>bindgen::Builder::no_copy</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-3" id="command-line-3">Command Line</a></h3> |
| <ul> |
| <li><code>--no-copy <regex></code></li> |
| </ul> |
| <h3><a class="header" href="#annotations-2" id="annotations-2">Annotations</a></h3> |
| <pre><code class="language-c">/** |
| * Although bindgen can't know, this struct is not safe to move because pthread |
| * mutexes can't move in memory! |
| * |
| * <div rustbindgen nocopy></div> |
| */ |
| struct MyMutexWrapper { |
| pthread_mutex_t raw; |
| // ... |
| }; |
| </code></pre> |
| <h1><a class="header" href="#preventing-the-derivation-of-debug" id="preventing-the-derivation-of-debug">Preventing the Derivation of <code>Debug</code></a></h1> |
| <p><code>bindgen</code> will attempt to derive the <code>Debug</code> traits on a best-effort |
| basis. Sometimes, it might not understand that although adding <code>#[derive(Debug)]</code> to a translated type definition will compile, it still shouldn't do |
| that for reasons it can't know. In these cases, the <code>nodebug</code> annotation can be |
| used to prevent bindgen to autoderive the <code>Debug</code> traits for a type.</p> |
| <h3><a class="header" href="#library-4" id="library-4">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_debug"><code>bindgen::Builder::no_debug</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-4" id="command-line-4">Command Line</a></h3> |
| <ul> |
| <li><code>--no-debug <regex></code></li> |
| </ul> |
| <h3><a class="header" href="#annotations-3" id="annotations-3">Annotations</a></h3> |
| <pre><code class="language-c">/** |
| * Although bindgen can't know, this enum is not safe to format the output. |
| * the value may be combined with multiple bits in many C/C++ cases, |
| * for example: |
| * |
| * <div rustbindgen nodebug></div> |
| */ |
| enum AVRounding { |
| AV_ROUND_ZERO = 0, |
| AV_ROUND_INF = 1, |
| AV_ROUND_DOWN = 2, |
| AV_ROUND_UP = 3, |
| AV_ROUND_NEAR_INF = 5, |
| AV_ROUND_PASS_MINMAX = 8192, |
| }; |
| |
| // Prototype |
| int64_t av_rescale_rnd(int64_t a, int64_t b, int64_t c, enum AVRounding) av_const; |
| |
| // Call |
| int64_t pts = av_rescale_rnd(40000, 3600, 90000, AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); |
| </code></pre> |
| <h1><a class="header" href="#preventing-the-derivation-of-default" id="preventing-the-derivation-of-default">Preventing the Derivation of <code>Default</code></a></h1> |
| <p><code>bindgen</code> will attempt to derive/impl the <code>Default</code> traits on a best-effort basis. |
| Sometimes, we need customize the implement of <code>Default</code> for certain types, |
| In these cases, the <code>nodefault</code> annotation can be used to prevent bindgen |
| to autoderive the <code>Default</code> traits for a type.</p> |
| <h3><a class="header" href="#library-5" id="library-5">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.no_default"><code>bindgen::Builder::no_default</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-5" id="command-line-5">Command Line</a></h3> |
| <ul> |
| <li><code>--no-default <regex></code></li> |
| </ul> |
| <h3><a class="header" href="#annotations-4" id="annotations-4">Annotations</a></h3> |
| <pre><code class="language-c">/** |
| * We need to specify some preset values as the Default of Header. |
| * |
| * for example: |
| * |
| * <div rustbindgen nodefault></div> |
| */ |
| struct Header { |
| unsigned int magic; |
| unsigned char data[252]; |
| }; |
| |
| ... |
| </code></pre> |
| <h3><a class="header" href="#customize-implements" id="customize-implements">Customize Implements</a></h3> |
| <pre><code class="language-rust ignore">// Include the generated bindings. |
| include!(concat!(env!("OUT_DIR"), "/bindings.rs")); |
| |
| impl Default for Header { |
| fn default() -> Self { |
| Self { |
| magic: 0x10203040u32, |
| data: [0; 252usize], |
| } |
| } |
| } |
| </code></pre> |
| <h1><a class="header" href="#annotating-types-with-must-use" id="annotating-types-with-must-use">Annotating types with <code>#[must-use]</code></a></h1> |
| <p><code>bindgen</code> can be instructed to annotate certain types with |
| <a href="https://doc.rust-lang.org/reference/attributes/diagnostics.html#the-must_use-attribute"><code>#[must_use]</code></a>.</p> |
| <p>Some libraries have a common error type, returned by lots of their functions, |
| which needs to be checked after every call. In these cases it's useful to add <code>#[must_use]</code> to this type, so the Rust |
| compiler emits a warning when the check is missing.</p> |
| <h3><a class="header" href="#library-6" id="library-6">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.must_use_type"><code>bindgen::Builder::must_use_type</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-6" id="command-line-6">Command Line</a></h3> |
| <ul> |
| <li><code>--must-use-type <regex></code></li> |
| </ul> |
| <h3><a class="header" href="#annotations-5" id="annotations-5">Annotations</a></h3> |
| <pre><code class="language-c">/** <div rustbindgen mustusetype></div> */ |
| struct ErrorType { |
| // ... |
| }; |
| |
| ... |
| </code></pre> |
| <h1><a class="header" href="#making-fields-private" id="making-fields-private">Making fields private</a></h1> |
| <p>Fields can be made private for various reasons. You may wish to enforce some invariant on the fields of a structure, which cannot be achieved if the field is public and can be set by any code. For example, you may wish to ensure that a pointer always points to something appropriate.</p> |
| <h3><a class="header" href="#annotation-1" id="annotation-1">Annotation</a></h3> |
| <pre><code class="language-c">struct OneFieldPrivate { |
| /** Null-terminated, static string. <div rustbindgen private> */ |
| const char *s; |
| bool b; |
| }; |
| |
| /** <div rustbindgen private> */ |
| struct MostFieldsPrivate { |
| int a; |
| bool b; |
| /** <div rustbindgen private="false"></div> */ |
| char c; |
| }; |
| </code></pre> |
| <p>Then in Rust:</p> |
| <pre><pre class="playground"><code class="language-rust"> |
| <span class="boring">#![allow(unused)] |
| </span><span class="boring">fn main() { |
| </span><span class="boring">#[repr(C)] |
| </span><span class="boring">pub struct OneFieldPrivate { |
| </span><span class="boring"> s: *const ::std::os::raw::c_char, |
| </span><span class="boring"> pub b: bool, |
| </span><span class="boring">} |
| </span> |
| impl OneFieldPrivate { |
| pub fn new(s: &'static std::ffi::CStr, b: bool) -> Self { |
| OneFieldPrivate { s: s.as_ptr(), b } |
| } |
| } |
| <span class="boring">} |
| </span></code></pre></pre> |
| <h1><a class="header" href="#code-formatting" id="code-formatting">Code Formatting</a></h1> |
| <p><code>bindgen</code> uses <code>rustfmt</code> to format the emitted bindings. This section describes |
| how to adjust the <code>rustfmt</code> behavior when being used from <code>bindgen</code>.</p> |
| <h2><a class="header" href="#passing-a-rustfmttoml-configuration-file" id="passing-a-rustfmttoml-configuration-file">Passing a <code>rustfmt.toml</code> configuration file</a></h2> |
| <p><code>rustfmt</code> should automatically use any <code>rustfmt.toml</code> file that is present in |
| the directory from where <code>bindgen</code> will be run. If you want to use a |
| configuration file that has a different name or that is in a different |
| directory you can use the <code>--rustfmt-configuration-file</code> flag or the |
| <a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.rustfmt_configuration_file"><code>Builder::rustfmt_configuration_file</code></a> |
| method.</p> |
| <h2><a class="header" href="#using-a-nightly-release-of-rustfmt" id="using-a-nightly-release-of-rustfmt">Using a nightly release of <code>rustfmt</code></a></h2> |
| <p>If the <code>rustfmt</code> command does not correspond to a nightly release of <code>rustfmt</code> |
| but you have <code>rustup</code> available, you can use <code>nightly</code> by following these |
| steps:</p> |
| <h3><a class="header" href="#when-using-bindgen-as-a-cli-application" id="when-using-bindgen-as-a-cli-application">When using <code>bindgen</code> as a CLI application</a></h3> |
| <p>Use <code>rustup run</code> to run <code>bindgen</code>:</p> |
| <pre><code class="language-bash">$ rustup run nightly bindgen [ARGS] |
| </code></pre> |
| <h3><a class="header" href="#when-using-bindgen-as-a-library" id="when-using-bindgen-as-a-library">When using <code>bindgen</code> as a library</a></h3> |
| <p>Take the output of the following command:</p> |
| <pre><code class="language-bash">$ rustup which rustfmt --toolchain=nightly |
| </code></pre> |
| <p>and pass it to |
| <a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.with_rustfmt"><code>Builder::with_rustfmt</code></a>:</p> |
| <pre><code class="language-rust ignore">use bindgen::Builder; |
| use std::process::Command; |
| |
| fn main() { |
| let output = Command::new("rustup") |
| .args(["which", "rustfmt", "--toolchain", "nightly"]) |
| .output() |
| .expect("Could not spawn `rustup` command"); |
| |
| assert!( |
| output.status.success(), |
| "Unsuccessful status code when running `rustup`: {:?}", |
| output |
| ); |
| |
| let rustfmt_path = |
| String::from_utf8(output.stdout).expect("The `rustfmt` path is not valid `utf-8`"); |
| |
| let bindings = Builder::default() |
| .header("path/to/input.h") |
| .with_rustfmt(rustfmt_path) |
| .generate() |
| .expect("Could not generate bindings"); |
| |
| bindings |
| .write_to_file("path/to/output.rs") |
| .expect("Could not write bindings"); |
| } |
| </code></pre> |
| <p>These two methods also apply to any other toolchain available in your system.</p> |
| <h2><a class="header" href="#using-prettyplease" id="using-prettyplease">Using <code>prettyplease</code></a></h2> |
| <p>The <a href="https://github.com/dtolnay/prettyplease"><code>prettyplease</code></a> crate is a |
| minimal formatter for generated code. To format bindings using <code>prettyplease</code> |
| you have to invoke <code>bindgen</code> with either the <code>--formatter=prettyplease</code> flag or |
| the <code>bindgen::Builder::formatter(bindgen::Formatter::Prettyplease)</code>. One of |
| its advantages is that <code>prettyplease</code> can be used in minimal environments where |
| the Rust toolchain is not installed.</p> |
| <h2><a class="header" href="#how-can-i-normalize-doc-attributes" id="how-can-i-normalize-doc-attributes">How can I normalize <code>#[doc]</code> attributes?</a></h2> |
| <p><code>bindgen</code> emits all the documentation using <code>#[doc]</code> attributes by default. If |
| you want to use the more user-friendly <code>///</code> syntax, you have two options:</p> |
| <h3><a class="header" href="#use-rustfmt" id="use-rustfmt">Use <code>rustfmt</code></a></h3> |
| <p><code>rustfmt</code> can be configured to normalize documentation. To do so, you have to |
| create a <code>rustfmt.toml</code> file with the following contents:</p> |
| <pre><code class="language-toml">normalize_doc_attributes = true |
| </code></pre> |
| <p>Then, you have set up <code>bindgen</code> so it passes this file to <code>rustfmt</code>. Given that |
| the <code>normalize_doc_attributes</code> option is |
| <a href="https://github.com/rust-lang/rustfmt/issues/3351">unstable</a>, you also have to |
| set up bindgen to use a <code>nightly</code> release of <code>rustfmt</code>.</p> |
| <h3><a class="header" href="#use-prettyplease" id="use-prettyplease">Use <code>prettyplease</code></a></h3> |
| <p><code>prettyplease</code> normalizes documentation without any additional configuration. |
| Then you just have to tell <code>bindgen</code> to use <code>prettyplease</code> as the code |
| formatter.</p> |
| <h1><a class="header" href="#generating-bindings-to-c" id="generating-bindings-to-c">Generating Bindings to C++</a></h1> |
| <p><code>bindgen</code> can handle some C++ features, but not all of them. To set |
| expectations: <code>bindgen</code> will give you the type definitions and FFI declarations |
| you need to build an API to the C++ library, but using those types in Rust will |
| be nowhere near as nice as using them in C++. You will have to manually call |
| constructors, destructors, overloaded operators, etc yourself.</p> |
| <p>When passing in header files, the file will automatically be treated as C++ if |
| it ends in <code>.hpp</code>. If it doesn't, adding <code>-x c++</code> clang args can be used to |
| force C++ mode. You probably also want to use <code>-std=c++14</code> or similar clang args |
| as well.</p> |
| <p>You pretty much <strong>must</strong> use <a href="./allowlisting.html">allowlisting</a> when working |
| with C++ to avoid pulling in all of the <code>std::.*</code> types, many of which <code>bindgen</code> |
| cannot handle. Additionally, you may want to mark other types as |
| <a href="./opaque.html">opaque</a> that <code>bindgen</code> stumbles on. It is recommended to mark |
| all of <code>std::.*</code> opaque, and to allowlist only precisely the functions and types |
| you intend to use.</p> |
| <p>You should read up on the <a href="./faq.html">FAQs</a> as well.</p> |
| <h2><a class="header" href="#supported-features" id="supported-features">Supported Features</a></h2> |
| <ul> |
| <li> |
| <p>Inheritance (for the most part; there are |
| <a href="https://github.com/rust-lang/rust-bindgen/issues/380">some outstanding bugs</a>)</p> |
| </li> |
| <li> |
| <p>Methods</p> |
| </li> |
| <li> |
| <p>Bindings to constructors and destructors (but they aren't implicitly or |
| automatically invoked)</p> |
| </li> |
| <li> |
| <p>Function and method overloading</p> |
| </li> |
| <li> |
| <p>Templates <em>without</em> specialization. You should be able to access individual |
| fields of the class or struct.</p> |
| </li> |
| </ul> |
| <h2><a class="header" href="#unsupported-features" id="unsupported-features">Unsupported Features</a></h2> |
| <p>When <code>bindgen</code> finds a type that is too difficult or impossible to translate |
| into Rust, it will automatically treat it as an opaque blob of bytes. The |
| philosophy is that</p> |
| <ol> |
| <li> |
| <p>we should always get layout, size, and alignment correct, and</p> |
| </li> |
| <li> |
| <p>just because one type uses specialization, that shouldn't cause <code>bindgen</code> to |
| give up on everything else.</p> |
| </li> |
| </ol> |
| <p>Without further ado, here are C++ features that <code>bindgen</code> does not support or |
| cannot translate into Rust:</p> |
| <ul> |
| <li> |
| <p>Inline functions and methods: see |
| <a href="./faq.html#why-isnt-bindgen-generating-bindings-to-inline-functions">"Why isn't <code>bindgen</code> generating bindings to inline functions?"</a></p> |
| </li> |
| <li> |
| <p>Template functions, methods of template classes and structs. We don't know |
| which monomorphizations exist, and can't create new ones because we aren't a |
| C++ compiler.</p> |
| </li> |
| <li> |
| <p>Anything related to template specialization:</p> |
| <ul> |
| <li>Partial template specialization</li> |
| <li>Traits templates</li> |
| <li>Substitution Failure Is Not An Error (SFINAE)</li> |
| </ul> |
| </li> |
| <li> |
| <p>Cross language inheritance, for example inheriting from a Rust struct in C++.</p> |
| </li> |
| <li> |
| <p>Automatically calling copy and/or move constructors or destructors. Supporting |
| this isn't possible with Rust's move semantics.</p> |
| </li> |
| <li> |
| <p>Exceptions: if a function called through a <code>bindgen</code>-generated interface |
| raises an exception that is not caught by the function itself, this will |
| generate undefined behaviour. See |
| <a href="https://github.com/rust-lang/rust-bindgen/issues/1208">the tracking issue for exceptions</a> |
| for more details.</p> |
| </li> |
| <li> |
| <p>Many C++ specific aspects of calling conventions. For example in the Itanium abi types that are |
| "<a href="https://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-trivial">non trivial for the purposes of calls</a>" |
| should be passed by pointer, even if they are otherwise eligible to be passed in a register. |
| Similarly in both the Itanium and MSVC ABIs such types are returned by "hidden parameter", much like |
| large structs in C that would not fit into a register. This also applies to types with any base classes |
| in the MSVC ABI (see <a href="https://learn.microsoft.com/en-us/cpp/build/x64-calling-convention?view=msvc-170#return-values">x64 calling convention</a>). |
| Because bindgen does not know about these rules generated interfaces using such types are currently invalid.</p> |
| </li> |
| </ul> |
| <h2><a class="header" href="#constructor-semantics" id="constructor-semantics">Constructor semantics</a></h2> |
| <p><code>bindgen</code> will generate a wrapper for any class constructor declared in the |
| input headers. For example, this headers file</p> |
| <pre><code class="language-c++">class MyClass { |
| public: |
| MyClass(); |
| void method(); |
| }; |
| </code></pre> |
| <p>Will produce the following code:</p> |
| <pre><code class="language-rust ignore">#[repr(C)] |
| #[derive(Debug, Copy, Clone)] |
| pub struct MyClass { |
| pub _address: u8, |
| } |
| extern "C" { |
| #[link_name = "\u{1}_ZN7MyClass6methodEv"] |
| pub fn MyClass_method(this: *mut MyClass); |
| } |
| extern "C" { |
| #[link_name = "\u{1}_ZN7MyClassC1Ev"] |
| pub fn MyClass_MyClass(this: *mut MyClass); |
| } |
| impl MyClass { |
| #[inline] |
| pub unsafe fn method(&mut self) { |
| MyClass_method(self) |
| } |
| #[inline] |
| pub unsafe fn new() -> Self { |
| let mut __bindgen_tmp = ::std::mem::MaybeUninit::uninit(); |
| MyClass_MyClass(__bindgen_tmp.as_mut_ptr()); |
| __bindgen_tmp.assume_init() |
| } |
| } |
| </code></pre> |
| <p>This <code>MyClass::new</code> Rust method can be used as a substitute for the <code>MyClass</code> |
| C++ constructor. However, the address of the value from inside the method will |
| be different than from the outside. This is because the <code>__bindgen_tmp</code> value |
| is moved when the <code>MyClass::new</code> method returns.</p> |
| <p>In contrast, the C++ constructor will not move the value, meaning that the |
| address of the value will be the same inside and outside the constructor. |
| If the original C++ relies on this semantic difference somehow, you should use the |
| <code>MyClass_MyClass</code> binding directly instead of the <code>MyClass::new</code> method.</p> |
| <p>In other words, the Rust equivalent for the following C++ code</p> |
| <pre><code class="language-c++">MyClass instance = MyClass(); |
| instance.method(); |
| </code></pre> |
| <p>is not this</p> |
| <pre><code class="language-rust ignore">let instance = MyClass::new(); |
| instance.method(); |
| </code></pre> |
| <p>but this</p> |
| <pre><code class="language-rust ignore">let instance = std::mem::MaybeUninit::<MyClass>::uninit(); |
| MyClass_MyClass(instance.as_mut_ptr()); |
| instance.assume_init_mut().method(); |
| </code></pre> |
| <p>You can easily verify this fact if you provide a implementation for <code>MyClass</code> |
| and <code>method</code> that prints the <code>this</code> pointer address. However, you can |
| ignore this fact if you know that the original C++ code does not rely on the |
| instance address in its internal logic.</p> |
| <h1><a class="header" href="#generating-bindings-to-objective-c" id="generating-bindings-to-objective-c">Generating Bindings to Objective-C</a></h1> |
| <p><code>bindgen</code> does not (yet) have full objective-c support but it can generate bindings |
| for a lot of the apple frameworks without too much blocklisting.</p> |
| <p>In order to generate bindings, you will need <code>-x objective-c</code> as the clang |
| args. If you'd like to use <a href="https://crates.io/crates/block">block</a> you will need |
| <code>-fblocks</code> as a clang arg as well.</p> |
| <p>Depending on your setup, you may need <code>--generate-block</code> to generate the block |
| function aliases and <code>--block-extern-crate</code> to insert a <code>extern crate block</code> at |
| the beginning of the generated bindings. The same logic applies to the |
| <code>--objc-extern-crate</code> parameter.</p> |
| <p>The objective-c classes will be represented as a <code>struct Foo(id)</code> and a trait |
| <code>IFoo</code> where <code>Foo</code> is the objective-c class and <code>id</code> is an alias for <code>*mut objc::runtime::Object</code> (the pointer to the objective-c instance). The trait |
| <code>IFoo</code> is needed to allow for the generated inheritance.</p> |
| <p>Functions that use or return objective-c pointers of instance <code>Foo</code> will return |
| <code>Foo</code>. The reason this works is because <code>Foo</code> represented as <code>transparent</code>. |
| This will be helpful for a lot of objective-c frameworks however there are some |
| cases where functions return <code>instancetype</code> which is a type alias for <code>id</code> so |
| an occasional <code>foo.0</code> may be required. An example of this would in the UIKit |
| framework should you want to add a <code>UILabel</code> to a |
| <a href="https://developer.apple.com/documentation/uikit/uistackview/1616227-addarrangedsubview?language=objc">UIStackView</a> |
| you will need to convert the <code>UILabel</code> to a <code>UIView</code> via <code>UIView(label.0)</code>.</p> |
| <p>Each class (struct) has an <code>alloc</code> and a <code>dealloc</code> to match that of some of the alloc |
| methods found in <code>NSObject</code>.</p> |
| <p>In order to initialize a class <code>Foo</code>, you will have to do something like <code>let foo = Foo(Foo::alloc().initWithStuff())</code>.</p> |
| <p>To blocklist an Objective-C method, you should add the bindgen generated method |
| path (e.g. <code>IFoo::method</code> or <code>IFoo::class_method</code>) as a blocklist item.</p> |
| <h2><a class="header" href="#supported-features-1" id="supported-features-1">Supported Features</a></h2> |
| <ul> |
| <li>Inheritance matched to rust traits with prefixes of <code>I</code> which |
| stands for interface.</li> |
| <li>Protocols which match to rust traits with prefixes of <code>P</code> which |
| stands for Protocol.</li> |
| <li>Classes will generate <code>struct Foo(id)</code> where <code>Foo</code> is the class |
| name and <code>id</code> is a pointer to the objective-c Object.</li> |
| <li>Blocks</li> |
| </ul> |
| <h2><a class="header" href="#useful-notes" id="useful-notes">Useful Notes</a></h2> |
| <ul> |
| <li>If you're targeting <code>aarch64-apple-ios</code>, you'll need to have the clang arg |
| <code>--target=arm64-apple-ios</code> as mentioned |
| <a href="https://github.com/rust-lang/rust-bindgen/issues/1211#issuecomment-569804287">here</a>.</li> |
| <li>The generated bindings will almost certainly have some conflicts so you will |
| have to blocklist a few things. There are a few cases of the parameters being |
| poorly named in the objective-c headers. But if you're using anything with |
| Core Foundation, you'll find that <code>time.h</code> as has a variable called timezone that |
| conflicts with some of the things in <code>NSCalendar.h</code>.</li> |
| <li>Some small subset of the function headers in the apple frameworks go against |
| apple's guidelines for parameter names and duplicate the names in the header |
| which won't compile as mentioned |
| <a href="https://github.com/rust-lang/rust-bindgen/issues/1705">here</a>.</li> |
| <li>instancetype return methods does not return <code>Self</code> for you given class, it |
| returns a <code>mut * objc::runtime::Objc</code> which is aliased as <code>id</code>. This is because |
| objective-c's inheritance doesn't perfectly match that of rusts.</li> |
| <li>Depending on what you're trying <code>bindgen</code> against, you may end up including |
| all of Core Foundation and any other frameworks. This will result in a very |
| long compile time.</li> |
| </ul> |
| <h2><a class="header" href="#not-yet-supported" id="not-yet-supported">Not (yet) Supported</a></h2> |
| <ul> |
| <li>Nullability attributes which return <code>Option</code>s.</li> |
| <li>Probably many other things. Feel free to <a href="https://github.com/rust-lang/rust-bindgen/issues">open an issue</a>.</li> |
| </ul> |
| <h1><a class="header" href="#example-crates" id="example-crates">Example crate(s)</a></h1> |
| <ul> |
| <li><a href="https://github.com/simlay/uikit-sys">uikit-sys</a></li> |
| </ul> |
| <h1><a class="header" href="#using-the-union-types-generated-by-bindgen" id="using-the-union-types-generated-by-bindgen">Using the Union Types Generated by Bindgen</a></h1> |
| <p><strong>NOTE</strong>: Rust 1.19 stabilized the <code>union</code> type (see Rust issue <a href="https://github.com/rust-lang/rust/issues/32836">#32836</a>).</p> |
| <p>You can pass the <code>--rust-target</code> option to tell <code>bindgen</code> to target a specific version of Rust. |
| By default, <code>bindgen</code> will target the latest stable Rust. |
| The <code>--rust-target</code> option accepts a specific stable version (such as "1.0" or "1.19") or "nightly".</p> |
| <p><strong>NOTE</strong>: The <code>--unstable-rust</code> option is deprecated; use <code>--rust-target nightly</code> instead.</p> |
| <p>In general, most interactions with unions (either reading or writing) are unsafe, meaning you must surround union accesses in an <code>unsafe {}</code> block.</p> |
| <p>For this discussion, we will use the following C type definitions:</p> |
| <pre><code class="language-c">typedef struct { |
| int32_t a; |
| int32_t b; |
| } alpha_t; |
| |
| typedef struct { |
| uint32_t c; |
| uint16_t d; |
| uint16_t e; |
| uint8_t f; |
| } beta_t; |
| |
| typedef union { |
| alpha_t alfa; |
| beta_t bravo; |
| } greek_t; |
| </code></pre> |
| <h2><a class="header" href="#relevant-bindgen-options" id="relevant-bindgen-options">Relevant Bindgen Options</a></h2> |
| <h3><a class="header" href="#library-7" id="library-7">Library</a></h3> |
| <ul> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.rust_target"><code>bindgen::Builder::rust_target()</code></a> <!-- Update when live --></li> |
| <li><a href="https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.derive_default"><code>bindgen::Builder::derive_default()</code></a></li> |
| </ul> |
| <h3><a class="header" href="#command-line-7" id="command-line-7">Command Line</a></h3> |
| <ul> |
| <li><code>--rust-target</code></li> |
| <li><code>--with-derive-default</code></li> |
| </ul> |
| <h2><a class="header" href="#which-union-type-will-bindgen-generate" id="which-union-type-will-bindgen-generate">Which union type will Bindgen generate?</a></h2> |
| <p>Bindgen can emit one of two Rust types that correspond to C unions:</p> |
| <ul> |
| <li>Rust's <code>union</code> builtin (only available in Rust >= 1.19, including nightly)</li> |
| <li>Bindgen's <code>BindgenUnion</code> (available for all Rust targets)</li> |
| </ul> |
| <p>Bindgen uses the following logic to determine which Rust union type to emit:</p> |
| <ul> |
| <li>If the Rust target is >= 1.19 (including nightly) AND each field of the union can derive <code>Copy</code>, then generate a <code>union</code> builtin.</li> |
| <li>Otherwise, generate a <code>BindgenUnion</code>.</li> |
| </ul> |
| <h2><a class="header" href="#using-the-union-builtin" id="using-the-union-builtin">Using the <code>union</code> builtin</a></h2> |
| <p>When using the <code>union</code> builtin type, there are two choices for initialization:</p> |
| <ol> |
| <li>Zero</li> |
| <li>With a specific variant</li> |
| </ol> |
| <pre><code class="language-rust ignore">mod bindings_builtin_union; |
| |
| fn union_builtin() { |
| // Initialize the union to zero |
| let x = bindings_builtin_union::greek_t::default(); |
| |
| // If `--with-derive-default` option is not used, the following may be used |
| // to initialize the union to zero: |
| let x = unsafe { std::mem::zeroed::<bindings_builtin_union::greek_t>() }; |
| |
| // Or, it is possible to initialize exactly one variant of the enum: |
| let x = bindings_builtin_union::greek_t { |
| alfa: bindings_builtin_union::alpha_t { |
| a: 1, |
| b: -1, |
| }, |
| }; |
| |
| unsafe { |
| println!("{:?}", z.alfa); // alpha_t { a: 1, b: -1 } |
| println!("{:?}", z.bravo); // beta_t { c: 1, d: 65535, e: 65535, f: 127 } |
| } |
| } |
| </code></pre> |
| <h2><a class="header" href="#using-the-bindgenunion-type" id="using-the-bindgenunion-type">Using the <code>BindgenUnion</code> type</a></h2> |
| <p>If the target Rust version does not support the new <code>union</code> type or there is a field that cannot derive <code>Copy</code>, then bindgen will provide union-like access to a <code>struct</code>.</p> |
| <p>Interacting with these unions is slightly different than the new <code>union</code> types. |
| You must access union variants through a reference.</p> |
| <pre><code class="language-rust ignore">mod bindings; |
| |
| fn bindgenunion() { |
| // `default()` or `zeroed()` may still be used with Bindgen's Union types |
| let mut x = bindings::greek_t::default(); |
| |
| // This will not work: |
| // let x = bindings::greek_t { |
| // alfa: bindings::alpha_t { |
| // a: 1, |
| // b: -1, |
| // }, |
| // }; |
| |
| // Instead, access the field through `.as_ref()` and `.as_mut()` helpers: |
| unsafe { |
| *x.alfa.as_mut() = bindings::alpha_t { |
| a: 1, |
| b: -1, |
| }; |
| |
| println!("{:?}", x.alfa.as_ref()); // alpha_t { a: 1, b: -1 } |
| println!("{:?}", x.bravo.as_ref()); // beta_t { c: 1, d: 65535, e: 65535, f: 0 } |
| } |
| </code></pre> |
| <p>If you attempt to access a <code>BindgenUnion</code> field directly, you will see errors like this:</p> |
| <pre><code class="language-text">error[E0308]: mismatched types |
| --> src/main.rs:44:15 |
| | |
| 44 | alfa: bindings::alpha_t { |
| | _______________^ |
| 45 | | a: 1, |
| 46 | | b: -1, |
| 47 | | }, |
| | |_________^ expected struct `bindings::__BindgenUnionField`, found struct `bindings::alpha_t` |
| | |
| = note: expected type `bindings::__BindgenUnionField<bindings::alpha_t>` |
| found type `bindings::alpha_t` |
| </code></pre> |
| <h1><a class="header" href="#using-the-bitfield-types-generated-by-bindgen" id="using-the-bitfield-types-generated-by-bindgen">Using the Bitfield Types Generated by Bindgen</a></h1> |
| <h2><a class="header" href="#bitfield-strategy-overview" id="bitfield-strategy-overview">Bitfield Strategy Overview</a></h2> |
| <p>As Rust does not support bitfields, Bindgen generates a struct for each with the following characteristics</p> |
| <ul> |
| <li>Immutable getter functions for each bitfield named <code><bitfield></code></li> |
| <li>Setter functions for each contiguous block of bitfields named <code>set_<bitfield></code></li> |
| <li>For each contiguous block of bitfields, Bindgen emits an opaque physical field that contains one or more logical bitfields</li> |
| <li>A static constructor <code>new_bitfield_{1, 2, ...}</code> with a parameter for each bitfield contained within the opaque physical field.</li> |
| </ul> |
| <h2><a class="header" href="#bitfield-examples" id="bitfield-examples">Bitfield examples</a></h2> |
| <p>For this discussion, we will use the following C type definitions and functions.</p> |
| <pre><code class="language-c">typedef struct { |
| unsigned int a: 1; |
| unsigned int b: 1; |
| unsigned int c: 2; |
| |
| } StructWithBitfields; |
| |
| // Create a default bitfield |
| StructWithBitfields create_bitfield(); |
| |
| // Print a bitfield |
| void print_bitfield(StructWithBitfields bfield); |
| </code></pre> |
| <p>Bindgen creates a set of field getters and setters for interacting with the bitset. For example, </p> |
| <pre><code class="language-rust ignore"> let mut bfield = unsafe { create_bitfield() }; |
| |
| bfield.set_a(1); |
| println!("a set to {}", bfield.a()); |
| bfield.set_b(1); |
| println!("b set to {}", bfield.b()); |
| bfield.set_c(3); |
| println!("c set to {}", bfield.c()); |
| |
| unsafe { print_bitfield(bfield) }; |
| </code></pre> |
| <p>will print out</p> |
| <pre><code class="language-text">a set to 1 |
| b set to 1 |
| c set to 3 |
| StructWithBitfields: a:1, b:1, c:3 |
| </code></pre> |
| <p>Overflowing a bitfield will result in the same behavior as in C/C++: the bitfield will be set to 0.</p> |
| <pre><code class="language-rust ignore"> let mut bfield = unsafe { create_bitfield() }; |
| bfield.set_a(1); |
| bfield.set_b(1); |
| bfield.set_c(12); |
| println!("c set to {} due to overflow", bfield.c()); |
| |
| unsafe { print_bitfield(bfield) }; |
| </code></pre> |
| <p>will print out</p> |
| <pre><code class="language-text">c set to 0 due to overflow |
| StructWithBitfields: a:1, b:1, c:0 |
| </code></pre> |
| <p>To create a new bitfield in Rust, use the bitfield allocation unit constructor.</p> |
| <p>Note: This requires the Builder's derive_default to be set to true, otherwise the necessary Default functions won't be generated.</p> |
| <pre><code class="language-rust ignore"> let bfield = StructWithBitfields{ |
| _bitfield_1: StructWithBitfields::new_bitfield_1(0,0,0), |
| ..Default::default() |
| }; |
| |
| unsafe { print_bitfield(bfield) }; |
| </code></pre> |
| <p>This will print out</p> |
| <pre><code class="language-text">StructWithBitfields: a:0, b:0, c:0 |
| </code></pre> |
| <h1><a class="header" href="#using-c-structures-with-flexible-array-members" id="using-c-structures-with-flexible-array-members">Using C structures with Flexible Array Members</a></h1> |
| <p>Since time immemorial, C programmers have been using what was called "the struct |
| hack". This is a technique for packing a fixed-size structure and a |
| variable-sized tail within the same memory allocation. Typically this looks |
| like:</p> |
| <pre><code class="language-c">struct MyRecord { |
| time_t timestamp; |
| unsigned seq; |
| size_t len; |
| char payload[0]; |
| }; |
| </code></pre> |
| <p>Because this is so useful, it was standardized in C99 as "flexible array |
| members", using almost identical syntax:</p> |
| <pre><code class="language-c">struct MyRecord { |
| time_t timestamp; |
| unsigned seq; |
| size_t len; |
| char payload[]; // NOTE: empty [] |
| }; |
| </code></pre> |
| <p>Bindgen supports these structures in two different ways.</p> |
| <h2><a class="header" href="#__incompletearrayfield" id="__incompletearrayfield"><code>__IncompleteArrayField</code></a></h2> |
| <p>By default, bindgen will generate the corresponding Rust structure:</p> |
| <pre><code class="language-rust ignore">#[repr(C)] |
| struct MyRecord { |
| pub timestamp: time_t, |
| pub seq: ::std::os::raw::c_uint, |
| pub len: usize, |
| pub payload: __IncompleteArrayField<::std::os::raw::c_char>, |
| } |
| </code></pre> |
| <p>The <code>__IncompleteArrayField</code> type is zero-sized, so this structure represents |
| the prefix without any trailing data. In order to access that data, it provides |
| the <code>as_slice</code> unsafe method:</p> |
| <pre><code class="language-rust ignore"> // SAFETY: there's at least `len` bytes allocated and initialized after `myrecord` |
| let payload = unsafe { myrecord.payload.as_slice(myrecord.len) }; |
| </code></pre> |
| <p>There's also <code>as_mut_slice</code> which does the obvious.</p> |
| <p>These are <code>unsafe</code> simply because it's up to you to provide the right length (in |
| elements of whatever type <code>payload</code> is) as there's no way for Rust or Bindgen to |
| know. In this example, the length is a very straightforward <code>len</code> field in the |
| structure, but it could be encoded in any number of ways within the structure, |
| or come from somewhere else entirely.</p> |
| <p>One big caveat with this technique is that <code>std::mem::size_of</code> (or |
| <code>size_of_val</code>) will <em>only</em> include the size of the prefix structure. if you're |
| working out how much storage the whole structure is using, you'll need to add |
| the suffix yourself.</p> |
| <h2><a class="header" href="#using-dynamically-sized-types" id="using-dynamically-sized-types">Using Dynamically Sized Types</a></h2> |
| <p>If you invoke bindgen with the <code>--flexarray-dst</code> option, it will generate |
| something not quite like this:</p> |
| <pre><code class="language-rust ignore">#[repr(C)] |
| struct MyRecord { |
| pub timestamp: time_t, |
| pub seq: ::std::os::raw::c_uint, |
| pub len: usize, |
| pub payload: [::std::os::raw::c_char], |
| } |
| </code></pre> |
| <p>Rust has a set of types which are almost exact analogs for these Flexible Array |
| Member types: the Dynamically Sized Type ("DST").</p> |
| <p>This looks almost identical to a normal Rust structure, except that you'll note |
| the type of the <code>payload</code> field is a raw slice <code>[...]</code> rather than the usual |
| reference to slice <code>&[...]</code>.</p> |
| <p>That <code>payload: [c_char]</code> is telling Rust that it can't directly know the total |
| size of this structure - the <code>payload</code> field takes an amount of space that's |
| determined at runtime. This means you can't directly use values of this type, |
| only references: <code>&MyRecord</code>.</p> |
| <p>In practice, this is very awkward. So instead, bindgen generates:</p> |
| <pre><code class="language-rust ignore">#[repr(C)] |
| struct MyRecord<FAM: ?Sized = [::std::os::raw::c_char; 0]> { |
| pub timestamp: time_t, |
| pub seq: ::std::os::raw::c_uint, |
| pub len: usize, |
| pub payload: FAM, |
| } |
| </code></pre> |
| <p>That is:</p> |
| <ol> |
| <li>a type parameter <code>FAM</code> which represents the type of the <code>payload</code> field,</li> |
| <li>it's <code>?Sized</code> meaning it can be unsized (ie, a DST)</li> |
| <li>it has the default type of <code>[c_char; 0]</code> - that is a zero-sized array of characters</li> |
| </ol> |
| <p>This means that referencing plain <code>MyRecord</code> will be exactly like <code>MyRecord</code> |
| with <code>__IncompleteArrayField</code>: it is a fixed-sized structure which you can |
| manipulate like a normal Rust value.</p> |
| <p>But how do you get to the DST part?</p> |
| <p>Bindgen will also implement a set of helper methods for this:</p> |
| <pre><code class="language-rust ignore">// Static sized variant |
| impl MyRecord<[::std::os::raw::c_char; 0]> { |
| pub unsafe fn flex_ref(&self, len: usize) -> &MyRecord<[::std::os::raw::c_char]> { ... } |
| pub unsafe fn flex_mut_ref(&mut self, len: usize) -> &mut MyRecord<[::std::os::raw::c_char]> { ... } |
| // And some raw pointer variants |
| } |
| </code></pre> |
| <p>These will take a sized <code>MyRecord<[c_char; 0]></code> and a length in elements, and |
| return a reference to a DST <code>MyRecord<[c_char]></code> where the <code>payload</code> field is a |
| fully usable slice of <code>len</code> characters.</p> |
| <p>The magic here is that the reference is a fat pointer, which not only encodes |
| the address, but also the dynamic size of the final field, just like a reference |
| to a slice is. This means that you get full bounds checked access to the |
| <code>payload</code> field like any other Rust slice.</p> |
| <p>It also means that doing <code>mem::size_of_val(myrecord)</code> will return the <em>complete</em> |
| size of this structure, including the suffix.</p> |
| <p>You can go the other way:</p> |
| <pre><code class="language-rust ignore">// Dynamic sized variant |
| impl MyRecord<[::std::os::raw::c_char]> { |
| pub fn fixed(&self) -> (&MyRecord<[::std::os::raw::c_char; 0]>, usize) { ... } |
| pub fn fixed_mut(&mut self) -> (&mut MyRecord<[::std::os::raw::c_char; 0]>, usize) { ... } |
| pub fn layout(len: usize) -> std::alloc::Layout { ... } |
| } |
| </code></pre> |
| <p>which takes the DST variant of the structure and returns the sized variant, |
| along with the number of elements are after it. These are all completely safe |
| because all the information needed is part of the fat <code>&self</code> reference.</p> |
| <p>The <code>layout</code> function takes a length and returns the <code>Layout</code> - that is, size |
| and alignment, so that you can allocate memory for the structure (for example, |
| using <code>malloc</code> so you can pass it to a C function).</p> |
| <p>Unfortunately the language features needed to support these methods are still unstable:</p> |
| <ul> |
| <li><a href="https://doc.rust-lang.org/beta/unstable-book/library-features/ptr-metadata.html">ptr_metadata</a>, |
| which enables all the fixed<->DST conversions, and</li> |
| <li><a href="https://doc.rust-lang.org/beta/unstable-book/library-features/layout-for-ptr.html">layout_for_ptr</a>, |
| which allows he <code>layout</code> method</li> |
| </ul> |
| <p>As a result, if you don't specify <code>--rust-target nightly</code> you'll just get the |
| bare type definitions, but no real way to use them. It's often convenient to add |
| the</p> |
| <pre><code class="language-bash">--raw-line '#![feature(ptr_metadata,layout_for_ptr)]' |
| </code></pre> |
| <p>option if you're generating Rust as a stand-alone crate. Otherwise you'll need |
| to add the feature line to your containing crate.</p> |
| <h1><a class="header" href="#frequently-asked-questions" id="frequently-asked-questions">Frequently Asked Questions</a></h1> |
| <!-- START doctoc generated TOC please keep comment here to allow auto update --> |
| <!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --> |
| <ul> |
| <li><a href="faq.html#why-isnt-bindgen-generating-methods-for-this-allowlisted-class">Why isn't <code>bindgen</code> generating methods for this allowlisted class?</a></li> |
| <li><a href="faq.html#why-isnt-bindgen-generating-bindings-to-inline-functions">Why isn't <code>bindgen</code> generating bindings to inline functions?</a></li> |
| <li><a href="faq.html#does-bindgen-support-the-c-standard-template-library-stl">Does <code>bindgen</code> support the C++ Standard Template Library (STL)?</a></li> |
| <li><a href="faq.html#how-to-deal-with-bindgen-generated-padding-fields">How to deal with bindgen generated padding fields?</a></li> |
| <li><a href="faq.html#how-to-generate-bindings-for-a-custom-target">How to generate bindings for a custom target?</a></li> |
| </ul> |
| <!-- END doctoc generated TOC please keep comment here to allow auto update --> |
| <h3><a class="header" href="#why-isnt-bindgen-generating-methods-for-this-allowlisted-class" id="why-isnt-bindgen-generating-methods-for-this-allowlisted-class">Why isn't <code>bindgen</code> generating methods for this allowlisted class?</a></h3> |
| <p>Are the methods <code>inline</code> methods, or defined inline in the class? For example:</p> |
| <pre><code class="language-c++">class Dooder { |
| public: |
| // Function defined inline in the class. |
| int example_one() { return 1; } |
| |
| // `inline` function whose definition is supplied later in the header, or in |
| // another header. |
| inline bool example_two(); |
| }; |
| |
| inline bool Dooder::example_two() { |
| return true; |
| } |
| </code></pre> |
| <p>If so, see |
| <a href="faq.html#why-isnt-bindgen-generating-bindings-to-inline-functions">"Why isn't <code>bindgen</code> generating bindings to inline functions?"</a></p> |
| <p>If not, consider filing an issue!</p> |
| <h3><a class="header" href="#why-isnt-bindgen-generating-bindings-to-inline-functions" id="why-isnt-bindgen-generating-bindings-to-inline-functions">Why isn't <code>bindgen</code> generating bindings to inline functions?</a></h3> |
| <p>These functions don't typically end up in object files or shared libraries with |
| symbols that we can reliably link to, since they are instead inlined into each |
| of their call sites. Therefore, we don't generate bindings to them, since that |
| creates linking errors.</p> |
| <p>However, if you are compiling the C/C++ yourself (rather than using a system |
| shared library, for example), then you can pass <code>-fkeep-inline-functions</code> or |
| <code>-fno-inline-functions</code> to <code>gcc</code> or <code>clang</code>, and invoke <code>bindgen</code> with either |
| the <code>bindgen::Builder::generate_inline_functions</code> method or the |
| <code>--generate-inline-functions</code> flag.</p> |
| <p>Note that these functions and methods are usually marked inline for a reason: |
| they tend to be hot. The above workaround makes them an out-of-line call, which |
| might not provide acceptable performance.</p> |
| <p>As an alternative, you can invoke <code>bindgen</code> with either the |
| <code>bindgen::Builder::wrap_static_fns</code> method or the <code>--wrap-static-fns</code> flag. |
| Which generates a C source file that can be compiled against the input headers |
| to produce Rust headers for <code>static</code> and <code>static inline</code> functions. See <a href="https://github.com/rust-lang/rust-bindgen/discussions/2405">How to |
| handle <code>static inline</code> functions</a> |
| for further information.</p> |
| <h3><a class="header" href="#does-bindgen-support-the-c-standard-template-library-stl" id="does-bindgen-support-the-c-standard-template-library-stl">Does <code>bindgen</code> support the C++ Standard Template Library (STL)?</a></h3> |
| <p>Sort of. A little. Depends what you mean by "support".</p> |
| <p>Most functions, methods, constructors, and destructors are inline in the |
| STL. That ties our hands when it comes to linking: <a href="faq.html#why-isnt-bindgen-generating-bindings-to-inline-functions">"Why isn't <code>bindgen</code> generating bindings to inline functions?"</a></p> |
| <p>As far as generating opaque blobs of bytes with the correct size and alignment, |
| <code>bindgen</code> can do pretty well. This is typically enough to let you use types that |
| transitively contain STL things. We generally recommend marking <code>std::.*</code> as |
| opaque, and then allowlisting only the specific things you need from the library |
| you're binding to that is pulling in STL headers.</p> |
| <h3><a class="header" href="#how-to-deal-with-bindgen-generated-padding-fields" id="how-to-deal-with-bindgen-generated-padding-fields">How to deal with bindgen generated padding fields?</a></h3> |
| <p>Depending the architecture, toolchain versions and source struct, it is |
| possible that bindgen will generate padding fields named <code>__bindgen_padding_N</code>. |
| As these fields might be present when compiling for one architecture but not |
| for an other, you should not initialize these fields manually when initializing |
| the struct. Instead, use the <code>Default</code> trait. You can either enable this when |
| constructing the <code>Builder</code> using the <code>derive_default</code> method, or you can |
| implement this per struct using:</p> |
| <pre><code class="language-rust ignore">impl Default for SRC_DATA { |
| fn default() -> Self { |
| unsafe { std::mem::zeroed() } |
| } |
| } |
| </code></pre> |
| <p>This makes it possible to initialize <code>SRC_DATA</code> by:</p> |
| <pre><code class="language-rust ignore">SRC_DATA { |
| field_a: "foo", |
| field_b: "bar", |
| ..Default::default() |
| } |
| </code></pre> |
| <p>In the case bindgen generates a padding field, then this field will |
| be automatically initialized by <code>..Default::default()</code>.</p> |
| <h3><a class="header" href="#how-to-generate-bindings-for-a-custom-target" id="how-to-generate-bindings-for-a-custom-target">How to generate bindings for a custom target?</a></h3> |
| <p>To generate bindings for a custom target you only need to pass the <code>--target</code> |
| argument to <code>libclang</code>. For example, if you want to generate bindings for the |
| <code>armv7a-none-eabi</code> target using the command line, you need to invoke <code>bindgen</code> |
| like so:</p> |
| <pre><code class="language-bash">$ bindgen <input_headers> -- --target=armv7a-none-eabi |
| </code></pre> |
| <p>If you are using <code>bindgen</code> as a library, you should call |
| <code>builder.clang_arg("--target=armv7a-none-eabi")</code> on your <code>builder</code>.</p> |
| |
| </main> |
| |
| <nav class="nav-wrapper" aria-label="Page navigation"> |
| <!-- Mobile navigation buttons --> |
| |
| |
| |
| |
| <div style="clear: both"></div> |
| </nav> |
| </div> |
| </div> |
| |
| <nav class="nav-wide-wrapper" aria-label="Page navigation"> |
| |
| |
| |
| </nav> |
| |
| </div> |
| |
| |
| |
| |
| |
| |
| |
| |
| <script type="text/javascript"> |
| window.playground_copyable = true; |
| </script> |
| |
| |
| |
| |
| |
| <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script> |
| <script src="mark.min.js" type="text/javascript" charset="utf-8"></script> |
| <script src="searcher.js" type="text/javascript" charset="utf-8"></script> |
| |
| |
| <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script> |
| <script src="highlight.js" type="text/javascript" charset="utf-8"></script> |
| <script src="book.js" type="text/javascript" charset="utf-8"></script> |
| |
| <!-- Custom JS scripts --> |
| |
| |
| |
| |
| <script type="text/javascript"> |
| window.addEventListener('load', function() { |
| window.setTimeout(window.print, 100); |
| }); |
| </script> |
| |
| |
| |
| </body> |
| </html> |