Help with windows specific code organization

Hi All,

I'm trying to add windows support for a library I'd like to use, the rust version of arrow.

The library currently uses some posix specific calls, one of them is posix_memalign, which is used in a function called allocate_aligned. Let's take this as an example.

I can use conditional compilation to use the windows equivalent. Here is how I would like allocate_aligned to work:

fn allocate_aligned(size: i64) -> Result<*const u8, ArrowError> {
  if cfg!(windows) {
    let page = unsafe { _aligned_malloc(size as libc::size_t,
                                        ALIGNMENT as libc::size_t) };
    match page {
      0 => panic!("Unable to allocate {} bytes", size),
      _ => Ok(unsafe {mem::transmute::<libc::size_t, *const u8>(page)})
    }

  } else {
    unsafe {
      let mut page: *mut libc::c_void = mem::uninitialized();
      let result = libc::posix_memalign(&mut page, ALIGNMENT, size as usize);
      match result {
        libc::ENOMEM => Err(ArrowError::out_of_memory(format!("malloc of size {} failed", size))),
        libc::EINVAL => Err(ArrowError::invalid(format!("invalid alignment parameter: {}", ALIGNMENT))),
        0 => Ok(mem::transmute::<*mut libc::c_void, *const u8>(page)),
        _ => panic!("unknown allocation result: {}", result)
      }
    }
  }
}

However, this does not work because libc::posix_memalign is not included in the libc namespace on windows but I was assuming that this would not be an issue as I am using conditional compilation...

I have looked at libc and they handle this kind of thing by creating separate modules and conditionally using them.

To do this I would have to create separate modules for the windows and posix specific code and conditionally use them. Is there any easier way of doing this that I'm missing?

You can also do:

#[cfg(windows)]
fn allocate_aligned(size: i64) -> Result<*const u8, ArrowError> {
    // windows specific code
}

#[cfg(not(windows))] // or #[cfg(unix)]
fn allocate_aligned(size: i64) -> Result<*const u8, ArrowError> {
    // posix impl
}

This is arguably cleaner than cfg! since cross-platform code isn't intermixed in a single function.

1 Like

@vitalyd works like a charm. Thanks so much! :grinning: