C#和C ++ / CX对象如何相关?

时间:2013-07-11 07:48:41

标签: windows-phone-8 windows-runtime native managed c++-cx

我有一个可供C#WP应用程序使用的WP C ++运行时组件。

在C ++ Runtime Component中,我有

public interface class ICallback
    {
    public:
        virtual void DoSomething();
    };

public ref class WindowsPhoneRuntimeComponent sealed
    {
    public:
        WindowsPhoneRuntimeComponent();
        void SetCallback(ICallback ^callback);
        IMap<Platform::String^, Platform::Object^>^ CreateDictionary();

    };

在C#应用程序中,我有 CallbackImp,实现ICallback。然后我做

CallbackImp cb = new CallbackImp ();
WindowsPhoneRuntimeComponent com = new WindowsPhoneRuntimeComponent();

// Set callback
com.SetCallback(cb);

// Get dictionary
IDictionary<string, object> dict = com.CreateDictionary();

我有以下问题

  1. cb com 是托管对象。那么C ++ / CX对象在哪里呢?我有 听说 cb com 指向某些C ++ / CX对象(驻留 在原生堆上),对吗?
  2. 如果.NET GC发布 cb com ,C ++ / CX对象如何? 然后发布?
  3. 当我将 cb 传递给Runtime组件时, cb 是否属于托管 还是原生堆?
  4. dict 驻留在哪里?谁会释放它?

1 个答案:

答案 0 :(得分:5)

没有任何关系。 C ++ / CX是一种纯粹的非托管语言扩展,旨在使WinRT类型的互操作变得容易。这实际上是COM类型。语法类似于托管C ++ / CLI语言,主要是因为它们旨在解决同样的问题,使非托管类型的互操作变得容易。

您的C#代码中也会出现类似的情况。更不明显的是,您的C#组件将托管类型公开为非托管WinRT类型。利用CLR内置的语言投影。而这反过来又利用了CLR中内置的现有COM互操作。它不是完全不可见的,你必须例如声明你的C#类密封,COM带来的限制只支持接口继承,而不是实现继承。和其他各种花絮一样,只需使用DateTimeOffset而不是DateTime,语言投影的副作用只映射DateTimeOffset。等等。

所以解决你的问题:

  1. 这里没有C ++ / CX对象,它们是COM服务器的实现细节。创建WinRT对象的底层低级API是RoCreateInstance(),与COM CoCreateInstance()函数相同。它使用类工厂来创建对象。该对象归服务器所有,除了普通的COM接口指针之外,它根本不会暴露给其他代码。
  2. 通过引用计数在COM中管理内存,从而管理WinRT。 IUnknown :: AddRef()添加了一个引用,IUnknown :: Release()发布了一个引用。当最后一次Release调用将计数减少到0时,服务器会销毁该对象.AdlectRef()调用会自动生成C ++ / CX代码中的 ref new 或对象引用赋值语句,Release()是当C ++ / CX引用超出范围时由编译器自动生成。与您在COM代码中使用的CComPtr和_com_ptr_t包装类完全相同的行为,但区别在于编译器会处理它而不是您必须自己创建智能指针。通过附加细节,这将删除CCW持有的托管对象引用。最终,它允许GC垃圾收集C#对象。
  3. GC堆上存在 cb 对象。如上所述,COM只公开接口指针,WinRT完全不知道对象实际存在的位置。类工厂和IUnknown方法隐藏了该细节
  4. 与3相同。