【问题标题】:C++/CLI from tracking reference to (native) reference - wrappingC++/CLI 从跟踪引用到(本机)引用 - 包装
【发布时间】:2012-08-09 12:55:12
【问题描述】:

我需要一个 C# 接口来通过 CLI 方言调用一些本机 C++ 代码。 C# 接口在所需参数前面使用 out 属性说明符。这转化为 C++/CLI 中的 % 跟踪引用。

我的方法具有以下签名和主体(它正在调用另一个本机方法来完成这项工作):

virtual void __clrcall GetMetrics(unsigned int %width, unsigned int %height, unsigned int %colourDepth, int %left, int %top) sealed
{
    mRenderWindow->getMetrics(width, height, colourDepth, left, top);
}

现在代码由于一些编译时错误(都与not being able to convert parameter 1 from 'unsigned int' to 'unsigned int &'有关)而无法编译。

作为一个谦虚的 C++ 程序员,在我看来,CLI 对于讲德语的人来说就像是荷兰语。可以做些什么来使这个包装器在 CLI 中正常工作?

【问题讨论】:

    标签: reference c++-cli clr pass-by-reference managed


    【解决方案1】:

    就像已删除的答案中也建议的那样,我做了显而易见的事情并使用局部变量来传递相关值:

     virtual void __clrcall GetMetrics(unsigned int %width, unsigned int %height, unsigned int %colourDepth, int %left, int %top) sealed
            {
                unsigned int w = width, h = height, c = colourDepth;
                int l = left, t = top;
                mRenderWindow->getMetrics(w, h, c, l, t);
                width = w; height = h; colourDepth = c; left = l; top = t;
            }
    

    这有点明显,因为跟踪引用的机制相当直观:它们受到垃圾收集器工作的影响,当它们很容易被放在其他地方时,它们并不像正常的 &references 那样真正静态/恒定在记忆中。因此,这是解决问题的唯一可靠方法。感谢最初的回答。

    【讨论】:

      【解决方案2】:

      如果你的参数在 C# 端使用 'out',你需要像这样定义你的 C++/CLI 参数:[Out] unsigned int ^%width

      这是一个例子:

      virtual void __clrcall GetMetrics([Out] unsigned int ^%width)
      {
          width = gcnew UInt32(42);
      }
      

      然后在你的 C# 端,你会得到 42:

      ValueType vt;
      var res = cppClass.GetMetrics(out vt);
      //vt == 42
      

      为了在 C++/CLI 端使用 [Out] 参数,您需要包括:

      using namespace System::Runtime::InteropServices;
      

      希望这会有所帮助!

      【讨论】:

      • 感谢您的回复,奇怪的是,我第一次尝试它时它没有编译(现在它没有!编译器错误)。是的,在 C# 接口中,引用参数前面有 out 属性。但这解决了只是将 % 跟踪的 ref 运算符放在它们前面(这也是编译器建议的方式 - 尽管我尝试使用 System::Runtime::InteropServices::Out 属性。问题是我需要将width 传递给正常的本机 C++ 例程。这不起作用(请参阅我关于转换失败的错误消息)。干杯!
      • 装箱值类型值是一个非常糟糕的主意。它也没有解决 OP 的问题。
      • 答案更新(感谢@HansPassant 的建议和初步解释)。 +1
      • 我知道这是问题所在,但认为它太明显了,甚至无法提及。当然,您不能直接将托管变量传递给本机 C++ 函数 :) 很高兴它可以工作!
      • 谢谢,它确实有效,即使它看起来像是一种奇怪的挠头方式.. :)。
      【解决方案3】:

      您可以使用 pin_ptr 以便在本机代码更改时“宽度”不会移动。托管端受到 pin_ptr 的影响,但如果您希望本机代码直接访问它而不使用“w”,我认为您无法解决这个问题。

      virtual void __clrcall GetMetrics(unsigned int %width, unsigned int %height, unsigned int %colourDepth, int %left, int %top) sealed
              {
                  pin_ptr<unsigned int> pw = &width; //do the same for height
                  mRenderWindow->getMetrics(*pw, h, c, l, t);
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-19
        • 1970-01-01
        相关资源
        最近更新 更多