C#和C++/CX对象是如何关联的



我有一个要由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#应用程序中,我有实现ICallbackCallbackImp。然后我做

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传递给Runtime组件时,cb是否属于托管还是原生堆
  4. dict位于何处?谁来发布它

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

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

因此,解决您的问题:

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

相关内容

  • 没有找到相关文章

最新更新