cbindgen icon indicating copy to clipboard operation
cbindgen copied to clipboard

How to generate headers for third party crate?

Open videni opened this issue 1 year ago • 7 comments

Here is a rust example to illustrate the problem

my current crate

use crate::canvas::Canvas;
// app_surface is third party crate
pub use app_surface::{AppSurface, IOSViewObj};

#[no_mangle]
pub extern "C" fn create_canvas(ios_obj: IOSViewObj) -> *mut libc::c_void {
    println!(
        "create_canvas, maximum frames: {}",
        ios_obj.maximum_frames
    );
    
    let obj = Canvas::new(AppSurface::new(ios_obj), 0_i32);
    
    let box_obj = Box::new(obj);
    // 将 box_obj 对象的内存管理权转交给调用方
    Box::into_raw(box_obj) as *mut libc::c_void
}

third party crate


#[repr(C)]
pub struct IOSViewObj {
    pub view: *mut Object,
    pub metal_layer: *mut c_void,
    pub maximum_frames: i32,
    pub callback_to_swift: extern "C" fn(arg: i32),
}

No header found for IOSViewObj, got warning:

WARN: Can't find IOSViewObj. This usually means that this type was incompatible or not found.

videni avatar Jan 11 '25 00:01 videni

Maybe you need to take a look at [parse] and potentially [parse.expand].

crazyboycjr avatar Jan 25 '25 03:01 crazyboycjr

I also encountered this problem and was unable to solve it.

@videni did you find a solution?

In general items that are or depend on items (structs, enums, consts) that are foreign to the crate won't be generated.

Also I noticed that making a const availabe under a different name doesn't work, regardless of the origin.

pub const MY_CONSTANT: [type] = crate_or_module::SOME_CONSTANT;

like so won't work.

embediver avatar Jun 12 '25 06:06 embediver

The way of doing this is using [parse] parse_deps = true (and also include).

emilio avatar Jun 12 '25 11:06 emilio

Thanks for the fast response, but unfortunately I run into errors with this turned on.

On the project in question I get this panic:

  thread 'main' panicked at /home/marvin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbindgen-0.29.0/src/bindgen/parser.rs:928:82:
  called `Result::unwrap()` on an `Err` value: "Unsupported type: Type::Slice { bracket_token: Bracket, elem: Type::Path { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: PathArguments::None }] } } }"
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

I created a little sandbox environment to investigate cbindgen stuff and got a different panic on that one:

  thread 'main' panicked at /home/marvin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/cbindgen-0.29.0/src/bindgen/ir/generic_path.rs:112:9:
  Option has 0 params but is being instantiated with 1 values
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

The sandbox environment is pretty simple but I didn't jet investigated what the minimal example to reproduce this is. In case you work on this and want an example, let me know.

embediver avatar Jun 23 '25 09:06 embediver

If you can post a repro here I'd be happy to take a look when time avails :)

emilio avatar Jun 23 '25 13:06 emilio

I found out, that this bug only occurs when generating C headers. It compiles fine when generating a C++ header. But also for C++, I see a bunch of stuff getting generated that is probably coming from rust's std or core crates.

Here is the minimal example (didn't want to create a repo just for that). cbindgen is called from build.rs. Its basically unimportant what gets included, the bug also appears when the crates are otherwise empty. Commenting language = "C" out results in a successful build.

Cargo.toml

[package]
name = "staticlib"
version = "0.1.0"
edition = "2024"

[lib]
crate-type = ["staticlib"]

[dependencies]
somedependency = { path = "../somedependency" }

[build-dependencies]
cbindgen = "0.29"

cbindgen.toml

language = "C"

[parse]
parse_deps = true

[export]
include = ["MyStruct"]

lib.rs

pub use somedependency::MyStruct;

pub const FOO: u8 = 42;

somedependency is just a blank lib with only the following struct defined:

#[repr(C)]
pub struct MyStruct {
    pub a: u8,
    pub b: u32,
}

embediver avatar Jun 24 '25 10:06 embediver

I have this problem as well. Maybe it has something to do with specifying dependencies by path?

worldofjoni avatar Nov 20 '25 16:11 worldofjoni