调用对象的方法也会破坏该对象时,是否建议使用SafeHandle?

时间:2018-09-25 10:55:16

标签: c# rust pinvoke ffi

有一个提供三个功能的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创建一个Vec并将其包装在Box中,将原始指针返回给调用者。现在,调用者负责适当释放分配。

push_to_vector拥有Box<Vec<f32>>moves the Vec out of the Box的所有权,从而释放了Box在此过程中分配的内存。然后,它将一个项目添加到向量中,在Box周围创建一个全新的Vec(具有关联的分配)并将其返回。

sum_vector也拥有Box<Vec<f32>>的所有权,将VecBox中移出并释放了内存分配。由于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();
    }
}

通常,建议使用SafeHandle来确定DLL函数返回的指针,例如,参见this questionthis example。我了解SafeHandle的目的主要是在某些意外情况发生时,在某些情况下调用析构函数。

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

0 个答案:

没有答案