Help with windows specific code organization


#1

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?


#2

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.


#3

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