5

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

在 C++ 运行时组件中,我有

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# 应用程序中,我 CallbackImpICallback. 然后我做

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

// Set callback
com.SetCallback(cb);

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

我有以下问题

  1. cbcom是托管对象。那么 C++/CX 对象在哪里呢?我听说cbcom指向一些 C++/CX 对象(它们驻留在本机堆上),对吗?
  2. 如果cbcom由 .NET GC 释放,那么 C++/CX 对象是如何释放的呢?
  3. 当我将cb传递给运行时组件时,cb属于托管堆还是本地堆?
  4. dict驻留在哪里?谁来释放它?
4

1 回答 1

6

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

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

所以解决你的问题:

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