【问题标题】:converting .net reference to c++ reference将 .net 引用转换为 C++ 引用
【发布时间】:2013-06-10 10:20:46
【问题描述】:

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

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

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

这不起作用,因为他未能将num 转换为float&

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

不幸的是,我有很多想要传递的 ref 变量,而且代码看起来很难看,而且我觉得 temp 变量是一个 hack。

有没有更好的办法解决?

【问题讨论】:

  • 添加 .net c++ 标签.. 这将使您的问题得到更多覆盖。

标签: c# c++ .net managed-c++


【解决方案1】:
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& 引用将是运行时的原始非托管指针,指向浮点值。这允许被调用者更新值。两者都只是运行时的普通指针,唯一的区别是垃圾收集器可以看到内部指针,但看不到非托管指针。 jitter 告诉它在哪里寻找托管指针,对于本机 C++ 函数没有这样的帮助,因为它没有被 jitted。

因此可以为非托管指针分配内部指针值。但是,当垃圾收集器在本机代码运行时运行时,会发生 非常 令人讨厌的事情。请注意,当程序中的其他线程分配内存时,可能会发生 GC。 GC 所做的一件重要的事情是 compact 堆,它将托管对象作为集合的一部分移动。一个非常理想的特性,它消除了堆中的漏洞,并通过改进引用的局部性使托管代码变得更快。麻烦的是,本机代码持有一个指针,指向该浮动在移动之前所在的位置。如果它通过指针写入,更新浮点值,它将损坏 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;
    }
}

对此你无能为力,这是一个非常基本的限制。

【讨论】:

    猜你喜欢
    • 2011-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 2018-10-19
    • 1970-01-01
    • 2012-02-12
    相关资源
    最近更新 更多