cbindgen icon indicating copy to clipboard operation
cbindgen copied to clipboard

cbingen fails to export public methods wrapped in a block

Open stusmall opened this issue 2 years ago • 3 comments

I ran into this problem wrapping a couple other crates together to automatically produce bindings for a library. I've reduced the bug down to just a crate with the following lib.rs:

#[no_mangle]
pub unsafe extern "C" fn hello_1() -> u32 {
    1
}


const _: () = {
    #[no_mangle]
    pub unsafe extern "C" fn hello_2() -> u32 {
        {
            2
        }
    }
};

When putting this through cbindgen I get the following output

#  cbindgen -l c
WARN: Skip hellorust::_ - (not `pub`).
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

uint32_t hello_1(void);

I'd expect to see both hello_1 and hello_2 in the outputted header file. Looking at the executable both are present in the symbol table:

nm target/debug/libhellorust.so | grep hello
00000000000065e0 T hello_1
00000000000065f0 T hello_2

Editing the const definition doesn't help. Instead of skipping because of the lack of pub, it does because of the zero type sized. It never follows inside the block

stusmall avatar Jan 30 '22 23:01 stusmall

Curious, what's the use case for such constructs?

emilio avatar Jan 31 '22 01:01 emilio

Great question. I have a core rust library that exposes its interface with safer_ffi. safer_ffi is library that uses macros to help automatically produce the interface, boilerplate and C header files. I believe it wraps methods like this to prevent identifier collisions but I'm not positive.

I ran into this bug while experimenting with maturin to easily build and package python packages. It is using cbindgen to produce the header file that is fed into the python library cffi. cbindgen would fail to include the methods created by safer_ffi so then they wouldn't be included in the cffi produced python API.

This whole thing is a bit redundant since safer_ffi is also producing header files. Luckily since filing this bug I found out there is a way to provide the safer_ffi produced header to maturin and skip the cbindgen step. Once I did that everything appears to be working great. Having that makes this bug a lot more esoteric. I've noticed other macros follow this pattern, but I don't know how many. This might be such a deep edge case its worth just closing the ticket until someone else hits it.

stusmall avatar Jan 31 '22 15:01 stusmall

Is this really a "public" method? I don't know how to access it from outside the module. (Of course just treating the declaration as though it were outside the block does not work: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=dd69d530d324d7019e0cf1dea465198f )

BatmanAoD avatar Mar 07 '22 20:03 BatmanAoD