Reputation: 2652
My goal is to create a C API where the user is required to provide a block of memory with a certain size. This size happens to be the size of a struct in my rust library, and so I'd like to extract the size of the rust struct and place it in a header file as a C macro.
The problem is that I'm cross-compiling my library, so I can't run a program on my computer that prints core::mem::size_of::<MyStruct>()
. But I can store that value in a const
variable in my library.
Is there any way to extract the value of this const
variable representing the size of my struct at compile time such that I can then paste it into a C header file?
Upvotes: 1
Views: 1333
Reputation: 125965
I think it would be wiser to approach this from the opposite direction: define a C struct in a .h
file that you will distribute with your library for consumers to use, and then declare the struct #[repr(C)]
in Rust (you could even have bindgen generate the declaration for you automatically from the .h
as part of your build).
Upvotes: 0
Reputation: 58805
Definitely do not do this:
In a new crate, import the type in question, and create a function that returns its size:
#[no_mangle]
pub fn size_of_mystruct() -> usize {
std::mem::size_of::<MyStruct>()
}
Get the LLVM-IR output:
CARGO_INCREMENTAL=0 cargo rustc -- --emit=llvm-ir -o ir
Make sure to add the --target
option too. This will create a few files, one which should have extension .ll
. The CARGO_INCREMENTAL=0
is important - without it, it will create lots of .ll
files, and who knows which is the right one! Open the file and search for size_of_mystruct
. You'll find something like this:
; Function Attrs: uwtable
define i64 @size_of_mystruct() unnamed_addr #0 !dbg !142 {
start:
; call core::mem::size_of
%0 = call i64 @_ZN4core3mem7size_of17hc5e3caf4d8826b98E(), !dbg !144
br label %bb1, !dbg !144
Search for the internal function being called here. (In this case _ZN4core3mem7size_of17hc5e3caf4d8826b98E
). It will look like this:
; core::mem::size_of
; Function Attrs: inlinehint uwtable
define internal i64 @_ZN4core3mem7size_of17hc5e3caf4d8826b98E() unnamed_addr #1 !dbg !67 {
start:
%tmp_ret = alloca i64, align 8
store i64 40, i64* %tmp_ret, align 8, !dbg !87
%0 = load i64, i64* %tmp_ret, align 8, !dbg !87
br label %bb1, !dbg !87
This is the important bit: store i64 40
. The struct is 40 bytes!
Automate the process!
Wait until the whole process mysteriously breaks.
Upvotes: 2