Как мне освободить byte[] C#, выделенный в Rust?C#

Место общения программистов C#
Ответить
Anonymous
 Как мне освободить byte[] C#, выделенный в Rust?

Сообщение Anonymous »

У меня есть функция Rust, которая передает массив байтов в C#:

Код: Выделить всё

#[no_mangle]
pub extern "C" fn get_bytes(len: &mut i32, bytes: *mut *mut u8) {
let mut buf : Vec = get_data();
buf.shrink_to_fit();

// Set the output values
*len = buf.len() as i32;
unsafe {
*bytes = buf.as_mut_ptr();
}

std::mem::forget(buf);
}
Из C# я могу вызвать его без сбоев. (Вместо сбоя я предполагаю, что это правильно, но не уверен на 100 %):

Код: Выделить всё

[DllImport("my_lib")] static extern void get_bytes(ref int len,
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref byte[] bytes);

void test()
{
int len = 0;
byte[] bytes = null;
get_bytes(ref len, ref bytes);
}
Тогда я использую байты, но понимаю, что Rust должен освободить эту память. Итак, у меня есть еще одна функция Rust, чтобы освободить его:

Код: Выделить всё

#[no_mangle]
pub extern "C" fn free_bytes(len: i32, bytes: *mut *mut u8) {
// also tried with: -------------- bytes: *mut u8
assert!(len > 0);

// Rebuild the vec
let v = unsafe { Vec::from_raw_parts(bytes, len as usize, len as usize) };

//println!("bytes to free: {:?}", v);

drop(v); // or it could be implicitly dropped
}
И соответствующий C#. При вызове мое приложение аварийно завершает работу:

Код: Выделить всё

[DllImport("my_lib")] extern void free_bytes(int len, ref byte[] bytes);

void test()
{
int len = 0;
byte[] bytes = null;
get_bytes(ref len, ref bytes);

// copy bytes to managed memory
bytes[] copy = new byte[len];
bytes.CopyTo(copy, 0);
// free the unmanaged memory
free_bytes(len, ref bytes); // crash occurs when executing this function
}
Я вижу, что Vec::from_parts_raw "крайне небезопасен". Потому что "

Код: Выделить всё

capacity
должна быть емкостью, с которой был выделен указатель.", я также пробовал передавать емкость между Rust и C# без сжатия, чтобы сохранить длину и емкость. Это также привело к сбою.
Я предполагаю, что from_parts_raw восстанавливает существующую память в куче, но я заметил, что содержимое байтов в C# (показанное в Visual Studio) не соответствует содержимому в Rust (через команду println «байты бесплатно»). Так является ли моя ошибка в том, как я восстанавливаю Vec для освобождения в типах, которые принимает Rust (например, *mut u8 vs *mut *mut u8), в моем C# DllImport, где-то еще?

Подробнее здесь: https://stackoverflow.com/questions/667 ... ed-in-rust
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C#»