首页 > 解决方案 > 当调用对象的方法也会破坏对象时,是否建议使用 SafeHandle?

问题描述

有一个 Rust 库提供了三个功能:

像这样:

#[no_mangle]
pub extern "C" fn initialize_vector() -> *mut Vec<f32> {
    Box::into_raw(Box::new(Vec::<f32>::new()))
}

#[no_mangle]
pub extern "C" fn push_to_vector(ptr: *mut Vec<f32>, x: f32) -> *mut Vec<f32> {
    if ptr.is_null() { return ptr; }
    let vector_box = unsafe { Box::from_raw(ptr) };
    let mut example_vector = *vector_box;
    example_vector.push(x);
    Box::into_raw(Box::new(example_vector))
}

#[no_mangle]
pub extern "C" fn sum_vector(ptr: *mut Vec<f32>) -> f32 {
    if ptr.is_null() { return 0.0; }
    let vector_box = unsafe { Box::from_raw(ptr) };
    let example_vector = *vector_box;
    return example_vector.iter().sum();
}

initialize_vector创建 aVec并将其包装在 a 中Box,将原始指针返回给调用者。调用者现在负责适当地释放分配。

push_to_vector取得 的所有权Box<Vec<f32>>Vec移出Box,释放Box进程中分配的内存。然后它将一个项目添加到向量中,在 周围创建一个全新的Box(具有相关分配)Vec并返回它。

sum_vector还取得 的所有权Box<Vec<f32>>,将Vec移出Box并释放内存分配。由于 的所有权Vec不会离开函数,Rust 会Vec在函数退出时自动释放与 相关的内存。

使用该库的 C# 代码可能如下所示:

using System;
using System.Runtime.InteropServices;

internal class Blabla
{
    [DllImport("Example")]
    unsafe static public extern IntPtr initialize_vector();

    [DllImport("Example")]
    unsafe static public extern IntPtr push_to_vector(IntPtr ptr, float x);

    [DllImport("Example")]
    unsafe static public extern float sum_vector(IntPtr ptr);

    static public unsafe void Main()
    {
        IntPtr vec_ptr = initialize_vector();
        vec_ptr = push_to_vector(vec_ptr, (float) 2.2);
        vec_ptr = push_to_vector(vec_ptr, (float) 3.3);
        float result = sum_vector(vec_ptr);
        // is the memory allocated for the vector in Rust freed right now?
        Console.WriteLine(string.Format("Result: {0}", result));
        Console.ReadLine();
    }
}

通常,建议使用SafeHandleDLL 函数返回的指针来完成,请参见例如this questionthis example。我知道 的目的SafeHandle主要是在某些情况下,当发生意外情况时调用析构函数。

由于在调用函数后没有必要释放 Rust 向量,在给定的情况下sum_vector是否仍然建议使用SafeHandle,如果是 - 如何?还是我可以保留代码原样,一切都很好?

标签: c#rustpinvokeffi

解决方案


推荐阅读