I am trying to compile my rust code into staticlib and I try to write function for use in C# programming langue. This is first time I try it.
I think I only need to export one function for C# code to use my lib, so I wrote this funtion
type Callback = extern "C" fn(u64);
#[no_mangle]
pub extern "C" fn laz2xyz(config_name: *const u8, length: usize, callback: Callback) {
let config_name = unsafe { std::slice::from_raw_parts(config_name, length) };
let config_name = String::from_utf8_lossy(config_name).to_string();
let config_name = std::path::PathBuf::from(config_name);
let xyz = ToXYZ::build(config_name).expect("Failed to initialize ToXYZ");
xyz.run(move |progress| {
callback(progress);
})
.expect("Failed to process files");
}
This function needs to get path to file and callback function. Callback function will report progress of execution to caller.
But I get this error
|
5 | #[no_mangle]
| ^^^^^^^^^ usage of unsafe attribute
|
help: wrap the attribute in unsafe(...)
|
5 | #[unsafe(no_mangle)]
| +++++++ +
But I don't understand why. I never seen #[unsafe(no_mangle)]. All code on internet I seen was using #[no_mangle]
If I change as sugested I get diffirent error
error: this public function might dereference a raw pointer but is not marked unsafe
--> src\exports\laz2xyz.rs:7:59
|
7 | let config_name = unsafe { std::slice::from_raw_parts(config_name, length) };
|
But this function is inside unsafe block? config_name is marked as problem
But code does compile. I am using Visual Studio Code
Can this error be false positive?
You have to mark your function as unsafe, too, because it takes a raw pointer as input, I believe.
Edit: I played around with this a bit and found out that the error comes from the clippy::not_unsafe_ptr_arg_deref lint. That's why your program compiles, but your editor shows you the error message. You still should mark your function as unsafe though, as you can't guarantee that the pointer is valid inside of your function, your caller has to do it.
Well… duh. It's just barely 2026 yet, Rust 2024 is not yet very common “on internet”.
Depends on what you mean by “false positive”: if you believe Rust should be able to magically read C# code and know that what you are doing is safe, then it could be considered “a false positive”, if you think that function that relies on safety constraints that are not part of it's public interface then you would mark it “unsafe” and write a comment that explains how that function is supposed to be used for the program to be correct.
That's the whole point of unsafe functions: unlike normal, safe, functions that can be used incorrectly and cause memory corruption (or worse) if used incorrectly.
I know PathBuf internally use OsString, but this is where my knowlage about OsString ends.
I looked at OsString documentation, and the only they to create OsString from &[u8] I found is
std::ffi::OsString::from_encoded_bytes_unchecked
but from reading documentation it feels to me unsafe. It also says it should be used for &[u8] made from to_encoded_bytes(). Documentation says it is trivial mater to convert String to OsString, so I will let PathBuf convert String to OsString internally.
At last for now, as I don't know that kind of *u8 I will get in C#.
It's designed to support platform-specific filenames. On POSIX platform you use from_vec, on Windows platform you use from_wide.
Pletforms themselves have different (and incompatible!) requirements for the filenames thus there are, obviously, no universal way to support everything.
Obviously. On Windows. On Unix every sequence of non-zero bytes may be a filename, Windows is different.
That's the core issue. You would need to find out how C# deal with limitations of different platforms before you'll be able to design the proper way to handle the difference.
Using from_utf8 may or may not be a good idea depending on what C# does on Windows.
It wasn't error, it was warning. And it wars precisely about the fact that unchecked dereference of pointer in the fn is bad idea if function is not marked as unsafe.