将.net引用转换为c++引用

本文关键字:引用 c++ 转换 net | 更新日期: 2023-09-27 18:17:35

我有一个名为innergetnum的c++函数,它获得作为参数的float& num

我用托管c++写了一个函数,代码如下:

void getnum(float% num)
{
    innercppclass.innergetnum(num);
}

它不工作,因为他未能将num转化为float&

我发现的唯一解决方案是使额外的临时变量float tmp,传递给innergetnum,然后将其分配给num

不幸的是,我有很多ref变量我想传递,代码看起来很丑,我觉得临时变量是一个hack。

有更好的解决方法吗?

将.net引用转换为c++引用

error C2664: 'innercppclass::getnum' : cannot convert parameter 1 from 'float' to 'float &'
An object from the gc heap (a dereferenced gc pointer) cannot be converted to a native reference

你忘记记录你正在处理的错误,这就是你看到的。这完全是由设计决定的,也是托管代码工作方式的基础。

托管函数的float%参数可以是指向托管对象的内部指针,就像ref类的字段一样。float&Reference在运行时将是一个原始的非托管指针,指向浮点值。它允许被调用者更新值。两者在运行时都只是普通的指针,唯一的区别是垃圾收集器可以看到内部指针,而不是非托管指针。抖动告诉它在哪里寻找托管指针,对于本地c++函数没有这样的帮助,因为它没有被jit。

所以给非托管指针赋内部指针值是可能的。然而,当垃圾收集器在本机代码运行的同时运行时,会发生一些非常糟糕的事情。注意,当程序中的其他线程分配内存时,可能会发生GC。GC做的一件重要的事情是压缩堆,它将托管对象作为集合的一部分移动。这是一个非常理想的特性,它消除了堆中的漏洞,并通过改进引用的局部性使托管代码更快。问题是,本机代码持有一个指针指向浮点数被移动之前的位置。如果它通过指针写入,更新浮点值,它将破坏 GC堆。

没有任何方法可以阻止本机代码这样做,它不知道指针值在内存中的位置,所以它不能更新它。内部指针没有这样的问题,但本机引用存在无法解决的问题。

因此编译器抱怨说,它不可能生成不会使程序迟早(通常是以后)崩溃的代码,而且堆损坏完全无法诊断。您已经找到了解决方法,您需要从而不是 GC堆的存储位置生成指针。栈没有问题,局部变量永远不会移动:

void Managed::getnum(float% num) { 
    float temp;
    innercppclass::getnum(temp); 
    num = temp;
}

否则,当您将void getnum(float%)转换为float getnum()时,您也会编写这种代码。或者在托管代码中更典型的,属性getter:

property float num {
    float get() { 
        float temp;
        innercppclass::getnum(temp); 
        return temp;
    }
}

这是一个非常基本的限制。