gpt4 book ai didi

c# - 我应该如何使用 &str、Option 和 String 编码 Rust 函数并在 C# 中使用它?

转载 作者:行者123 更新时间:2023-11-29 08:06:05 26 4
gpt4 key购买 nike

以下代码在 Rust 中:

#[no_mangle]
#[cfg(not(target_arch = "wasm32"))]
pub extern fn generate_work(input_hash: &str, max_iters: Option<u64>) -> Option<String> {
let bytes = Vec::from_hex(input_hash).unwrap();
generate_work_internal(&bytes[..], max_iters)
}

我在 C# 中有以下代码:

[DllImport("mydll.dll")]
private static extern string generate_work(string input_hash, ulong[] max_iters);

我收到错误:

System.AccessViolationException: 'Attempted to read or write protected memory. This is often an indication that other memory is corrupt.'

我尝试过其他签名,但都没有用。

最佳答案

如我的 FFI Omnibus 中所述,您不能通过 FFI 函数传递复杂的特定于 Rust 的类型。您必须仅使用 C ABI 已知的类型。在您的示例中,这些类型是未知的:

  • &str
  • Option
  • String

相反,您将只需要使用基本的 C 指针。 NULL 指针可以表示 None对于字符串,但对于 Option<u64> ,您需要将其分解为两个值,一个 bool 值和一个实际值。您的 FFI 函数将类似于:

extern crate libc;

use std::ffi::{CStr, CString};
use std::ptr;

#[no_mangle]
#[cfg(not(target_arch = "wasm32"))]
pub extern "C" fn generate_work(
input_hash: *const libc::c_char,
max_iters_present: bool,
max_iters: u64,
) -> *const libc::c_char {
let input_hash = if input_hash.is_null() {
return ptr::null();
} else {
unsafe { CStr::from_ptr(input_hash) }
};
let input_hash = match input_hash.to_str() {
Ok(s) => s,
Err(_) => return ptr::null(),
};
let max_iters = if max_iters_present {
Some(max_iters)
} else {
None
};

let result = inner_code(input_hash, max_iters);

match result {
Some(s) => {
match CString::new(s) {
Ok(s) => s.into_raw(),
Err(_) => ptr::null(),
}
},
None => ptr::null(),
}
}

请注意,这会返回一个已分配的字符串,您需要将其传回给 Rust 以解除分配。同样,如 the FFI Omnibus 中所述, 你需要类似的东西

#[no_mangle]
pub extern fn free_a_string(s: *mut c_char) {
unsafe {
if s.is_null() { return }
CString::from_raw(s)
};
}

Converting a string to Rust is easy :

[DllImport("string_arguments", EntryPoint="how_many_characters")]
public static extern uint HowManyCharacters(string s);

Returning a string requires a lot more trickery, sadly :

internal class Native
{
[DllImport("string_return")]
internal static extern ThemeSongHandle theme_song_generate(byte length);
[DllImport("string_return")]
internal static extern void theme_song_free(IntPtr song);
}

internal class ThemeSongHandle : SafeHandle
{
public ThemeSongHandle() : base(IntPtr.Zero, true) {}

public override bool IsInvalid
{
get { return false; }
}

public string AsString()
{
int len = 0;
while (Marshal.ReadByte(handle, len) != 0) { ++len; }
byte[] buffer = new byte[len];
Marshal.Copy(handle, buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer);
}

protected override bool ReleaseHandle()
{
Native.theme_song_free(handle);
return true;
}
}

另见:

关于c# - 我应该如何使用 &str、Option 和 String 编码 Rust 函数并在 C# 中使用它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49091715/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com