I have a C ++ / cli binding which uses the c ++ library (which does not use com). I was surprised by the fact that if you explicitly mark all managed classes with the ComVisible (false) attribute, then I get a runtime error "query interface was made from non com visible class". This interface is generally com'vsky. I do not understand how such a situation is possible at all. I assumed that clr uses pinvoke calls for such purposes.
The class hierarchy is as follows:
Fragment of native code (dropped in process (when calling a functor))
// Native code class NativeItem { public: template<class ItemType> void process(const std::function<void(ItemType&)>& functor) { for (auto location = m_components.begin(); location != m_components.end(); ++location) functor(**location); } // Some stuff std::vector<NativeItem*> m_components; };
Excerpt C ++ / Cli code:
inline System::IntPtr convert(System::Delegate^ source_delegate) { return System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(source_delegate); } [System::Runtime::InteropServices::ComVisibleAttribute(false)] public ref class ManagedItem { protected: ManagedItem(NativeItem& native_item) : m_native_item(native_item) { } private: NativeItem& m_native_item; }; public ref class DerivedManagedItem : ManagedItem { public: DerivedManagedItem(NativeItem& native_item) : ManagedItem(native_item) { } }; public ref class Manager { public: typedef void (*create_managed_item_func)(NativeItem& item); delegate DerivedManagedItem^ CreateManagedItemDelegate(NativeItem& item); DerivedManagedItem^ create_item(NativeItem& item) { return gcnew DerivedManagedItem(item); } void process(NativeItem& item) { CreateManagedItemDelegate^ create_item_delegate = gcnew CreateManagedItemDelegate(this, &Manager::create_item); create_managed_item_func function_pointer = static_cast<create_managed_item_func>(convert(create_item_delegate).ToPointer()); component.process(function_pointer); System::GC::KeepAlive(create_item_delegate); } };