Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting raw pointer to 16-bit Unicode character to file path in Rust

I'm replacing a DLL written in C++ with one written in Rust. Currently the function in the DLL is called as follows:

BOOL calledFunction(wchar_t* pFileName)

I believe that in this context wchar_t is a 16-bit Unicode character, so I chose to expose the following function in my Rust DLL:

pub fn calledFunction(pFileName: *const u16)

What would be the best way to convert that raw pointer to something I could actually use to open the file from the Rust DLL?

like image 522
watts Avatar asked Feb 02 '18 16:02

watts


1 Answers

Here is some example code:

use std::ffi::OsString;
use std::os::windows::prelude::*;

unsafe fn u16_ptr_to_string(ptr: *const u16) -> OsString {
    let len = (0..).take_while(|&i| *ptr.offset(i) != 0).count();
    let slice = std::slice::from_raw_parts(ptr, len);

    OsString::from_wide(slice)
}

// main example
fn main() {
    let buf = vec![97_u16, 98, 99, 100, 101, 102, 0];
    let ptr = buf.as_ptr(); // raw pointer

    let string = unsafe { u16_ptr_to_string(ptr) };

    println!("{:?}", string);
}

In u16_ptr_to_string, you do 3 things:

  • get the length of the string by counting the non-zero characters using offset (unsafe)
  • create a slice using from_raw_parts (unsafe)
  • transform this &[u16] into an OsString with from_wide

It is better to use wchar_t and wcslen from the libc crate and use another crate for conversion. This is maybe a bad idea to reimplement something that is already maintained in a crate.

like image 85
Boiethios Avatar answered Nov 05 '22 16:11

Boiethios