rust-bindgen: libbindgen: error: expected type, found keyword `type`

rustc 1.15.0-nightly (daf8c1dfc 2016-12-05) libbindgen = “0.1.2” clang 3.9.0-3 opencv 3.1.0-6 Arch Linux 64-bit

wrapper.hpp

#include <opencv2/core/core.hpp>

build.rs

extern crate libbindgen;

use std::env;
use std::path::PathBuf;

fn main() {
    println!("cargo:rustc-link-lib=opencv_core");

    let bindings = libbindgen::Builder::default()
        .header("wrapper.hpp")
        .generate()
        .expect("Unable to generate bindings");

    let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
    bindings.write_to_file(out_path.join("bindings.rs"))
        .expect("Couldn't write bindings!");
}
$ cargo build
    Blocking waiting for file lock on build directory
   Compiling opencv v0.1.0 (file:///home/bruno/dev/rust/opencv)
error: expected type, found keyword `type`
    --> /home/bruno/dev/rust/opencv/target/debug/build/opencv-b0a1388c401941c1/out/bindings.rs:3367:46
     |
3367 |                                           -> type-parameter-0-1>,
     |                                              ^^^^

error: Could not compile `opencv`.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 19 (14 by maintainers)

Commits related to this issue

Most upvoted comments

So the failures are mostly expected.

On one hand, there’s a failure with the Scalar type. We can’t do much about it since it’s defined in terms of number generics:

template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>

The other ones are the std::vector type and std::string on my system. That’s because we don’t do associated types properly, and we end up getting a byte-sized type instead of a pointer-sized type. We can fix that with better info from libclang.

All the rest are derived from those. There’s additionally the std::vector<bool> specialization, that is something that we could indeed special-case as a one-off, but otherwise it’s template specialization madness we can’t support on rust.

If you find one of these problems, there are multiple ways to work around the problem, depending on needs.

If you don’t need to access the members, the easiest thing is marking stuff as opaque. Marking a type as opaque tries to replace that type with a proper replacement in each situation. For example:

.opaque_type("std::vector")

Would fix a bunch of tests, and replace the fields with properly-aligned arrays in rust.

Other possible workaround/fix, for when you need access to the type’s field, would be using replacements. For example, I know that std::vector is represented by three words in the STL, one pointer to the initial element, other to the last element, and other to the end of the reserved storage.

I could make the wrapper.h file look as follows:

/**
 * <div rustbindgen replaces="std::vector"></div>
 */
template<typename T, typename Alloc>
class vector_replacement {
  T* start;
  T* end;
  T* storage_end;
};

#include <opencv2/core.hpp>

That will replace the definition of std::vector by the type I just wrote, that bindgen can detect correctly. This wouldn’t fix the vector<bool> problem, but since we don’t use it, it seems to be a nice solution if we needed access to it.

Combining those configuration options, you can ensure the layout of your types is correct, even when bindgen can’t quite do the correct thing.

I’m not sure if I missed something (this should probably be documented in a more visible place). @fitzgen may correct me if I’m wrong.