mozilla / mozilla/cbindgen

Cannot generate corresponding C/C++ structure with `#![feature(generic_const_exprs)]`

Open
#1,157 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
3k
Forks
386
Avg merge
1h 43m
Merged PRs (30d)
1

Description

The minimum test sample of lib.rs:

#![allow(incomplete_features)]
#![feature(generic_const_exprs)]

pub const N_BYTE_PER_FRAME: usize = 8192;

#[repr(C)]
pub struct Payload<T>
where
    [(); N_BYTE_PER_FRAME / std::mem::size_of::<T>()]: Sized,
    T: Sized + Default + 'static,
{
    pub data: [T; N_BYTE_PER_FRAME / std::mem::size_of::<T>()],    //Code 1
    //pub data: T,   //Code 2
}


#[unsafe(no_mangle)]
pub extern "C" fn use_payload_ci16(_p: Payload<i16>){
}

Note the above two lines with comments Code 1 and Code 2

When uncomment Code 1 (pub data: [T; N_BYTE_PER_FRAME / std::mem::size_of::<T>()]), cbindgen only generate a blank wrapper of Payload:

template<typename T = void>
struct Payload;

extern "C" {

void use_payload_ci16(Payload<int16_t> _p);

}  // extern "C"

}  // namespace test_gen

When uncomment Code 2 and comment Code 1, cbindgen works normally and generate a corresponding C++ wrapper:

template<typename T>
struct Payload {
  T data;
};

extern "C" {

void use_payload_ci16(Payload<int16_t> _p);
...

My build.rs:

use std::{env::var, fs, path::PathBuf};

pub fn main() {
    println!("cargo:rerun-if-changed=src/");
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=Cargo.toml");
    println!("cargo:rerun-if-changed=cbindgen.toml");

    let crate_dir = var("CARGO_MANIFEST_DIR").unwrap();
    let include_dir = PathBuf::from(&crate_dir).join("include");
    if !include_dir.exists() {
        fs::create_dir_all(&include_dir).expect("Failed to create include directory");
    }

    let header_path = include_dir.join("syncdaq.h");

    cbindgen::Builder::new()
        .with_crate(crate_dir)
        .with_config(cbindgen::Config::from_file("cbindgen.toml").unwrap())
        .generate()
        .unwrap()
        .write_to_file(header_path);
}

and the cbindgen.toml:

language = "C++"
include_guard = "TEST_GEN"
namespace = "test_gen"

[export]
include=["Payload"]

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the minimal Rust sample in lib.rs and reproduce generation through build.rs using cbindgen.toml. Trace how cbindgen handles the generic Payload field containing an array length based on generic_const_exprs, comparing it with the T data case. Done means the generated C++ wrapper includes the data field for Code 1 while preserving the existing function declaration.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.