How to handle pthread platform differences with bindgen generated code?

I am trying to create a sys-library crate libindigo-sys for INDIGO using bindgen.

So far it works on Mac, but when I try to compile the rust libindigo wrapper library on Linux, I run into the following problem:

error[E0308]: mismatched types
  --> src/server.rs:23:17
   |
23 |         thread: ptr::null_mut(),
   |                 ^^^^^^^^^^^^^^^ expected `u64`, found `*mut _`
   |
   = note:     expected type `u64`
           found raw pointer `*mut _`

Evidently the pthreads are managed differently on Linux and Mac, no surprise there.

The error above relates to this snippet:

    let mut entry = indigo_server_entry {
        name: name,
        host: host,
        port: port,
        connection_id: 0,
        thread: ptr::null_mut(), // <-- bindgen on Mac produces a pointer, not an u64
        thread_started: false,
        socket: 0,
        protocol_adapter: ptr::null_mut(), 
        last_error: [0; 256],
        shutdown: false,
    };

Note that I only need to create instances of this struct and provide it to various C functions, I do not need to manipulate these threads in my Rust code.

Question is, how do I manage this in my wrapper code?

An alternative is to not handle it and tweak bindgen's code generation.

A quick hack for it could be to use std::mem::zeroed() which will give you a zero value for pointers and integers.

You could also try defining types and default values for it in Rust, using #[cfg(target_os = "macos")] and similar (see cfg_if), if the types change predictably on the platforms you support.

If the required type is exported by the C headers as a typedef, then bindgen should generate it. If there isn't a typedef, you could make one yourself by including original .h files in your wrapper.h.

If the types are too C-specific or too platform-specific, you could write a C function for initializing this struct, and build and link that C code as part of your sys crate.

1 Like

This "quick hack" works perfectly for the Mac/Linux difference, will be interesting to know when what happens when I test it on Windows...

You could also try defining types and default values for it in Rust, using #[cfg(target_os = "macos")] and similar (see cfg_if), if the types change predictably on the platforms you support.

Would this work though?

The code generated on a Mac requires a ptr::null_mut and on Linux, the bindgen code requires a u64 integer instead.

Note that I don't really care about the field as long as it gets intialised to zero or null, whatever is suitable on the platform. The C code will set it to the correct platform-specific value when the server is starting.

If the required type is exported by the C headers as a typedef, then bindgen should generate it. If there isn't a typedef, you could make one yourself by including original .h files in your wrapper.h .

The type does get generated, the issue is that bindgen generates (slightly) different code on Mac and Linux.

If the types are too C-specific or too platform-specific, you could write a C function for initializing this struct, and build and link that C code as part of your sys crate.

This would be the very last resort for me, but it is a good and valid option I think. Might be the cleanest although I would have to include custom c-code in my Rust crate instead of just relying on the upstream lib.

Thanks a lot for the pointers, they helped me to move on to the next issue regarding linking the static lib file...

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.