Страницы

Поиск по вопросам

пятница, 24 января 2020 г.

Почему CLR использует com объекты для совместимости управляемого и нативного кода?

#net #visual_cpp #cpp_cli


У меня есть C++/cli обвязка, которая использует c++ библиотеку (которая не использует
com). Меня удивил тот факт, что если явно пометить все управляемые классы атрибутом
ComVisible(false), то я получаю ошибку времени исполнения "query interface was made
from non com visible class". Этот интерфейс вообще com'вский. Не понимаю, как такая
ситуация вообще возможна. Я предполагал, что clr использует pinvoke вызовы для таких целей.

Иерархия классов следующая: 

Отрывок нативного кода (выпадает в process (при вызове функтора))

// Native code
class NativeItem
{
public:
     template
     void process(const std::function& functor)
     {
        for (auto location = m_components.begin(); location != m_components.end();
++location)
           functor(**location);
     }
// Some stuff
      std::vector m_components;
};


Отрывок C++/Cli кода:

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(convert(create_item_delegate).ToPointer());
        component.process(function_pointer);
        System::GC::KeepAlive(create_item_delegate);
   }
};

    


Ответы

Ответ 1



Из комментария пользователя @AlexAkel: Проблему уже нашел. Оказывается, у меня при вызове функции в нативном коде возвращался управляемый объект. Это можно увидеть по сигнатуре делегата CreateManagedItemDelegate.

Комментариев нет:

Отправить комментарий