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); } }; 
  • with # assumes by default that the classes used by the c ++ library will be com-s. - nick_n_a
  • This moment is incomprehensible, why crt uses com technology, I thought it exists only for compatibility of old com-classes - LmTinyToon
  • Not quite correctly replied, c # can exchange with native (c ++) only COM-related classes, C # has procedures that "help" bring the class to COM-compatible (the same IDIspatch builder to get access to the class fields), when trying To export a COM incompatible class, you get an exception. COM uses a rather narrow set of interfaces that provide class visibility and memory management: IUnknown, IDispatch, and several others. - nick_n_a
  • one
    @AlexAkel give the full text of the error and the stack trace! - Pavel Mayorov
  • one
    I have already found the problem, it turns out that when I called the function, the managed object was returned in the native code. This can be seen by the signature CreateManagedItemDelegate - LmTinyToon

1 answer 1

From @AlexAkel's comment :

Already found a problem. It turns out that when I called a function in the native code, the managed object was returned. This can be seen by the signature of the CreateManagedItemDelegate delegate.