本机到托管边界

时间:2016-06-10 02:42:30

标签: c++ .net callback c++-cli mixed-mode

我开发了托管C ++应用程序,它将ManagedSubscription的对象返回给C#客户端 ManagedSubscription接收来自C#客户端的回调,在内部进行回调以与本机C ++代码进行通信 在越过从原生到管理的界限时,我发现了一次崩溃 我已将try-catch置于本机和托管回调中,但它没有被捕获。

这是我的托管C ++代码:

    struct NativeCallbackWrapper
      {
      public:
        typedef std::function<bool(const std::vector<Sample>&, bool)> Callback_t;
        typedef bool(*CallbackPtr)(const std::vector<Sample>&, bool);

        NativeCallbackWrapper(Callback_t callback)
          : m_callback(callback)
        {
        }

        ~NativeCallbackWrapper()
        {
        }

        const Callback_t                                            m_callback;
      };


      //Here is decalred variables in ManagedSubscription.h file
      typedef std::function<bool(const std::vector<DFS::Chart::Misc::Sample>&, bool)> Callback_t;
      typedef bool(*CallbackPtr)(const std::vector<DFS::Chart::Misc::Sample>&, bool);
      delegate bool DelegateFunc(const std::vector<DFS::Chart::Misc::Sample>&, bool);

      NativeCallbackWrapper                        *m_nativeCallbackWrapper;
      System::Action<TradeResponse, bool>^         m_callback;
      DelegateFunc^                                m_delegate;
      System::Runtime::InteropServices::GCHandle   m_delegateHandle;


      //This object is returned to C# application
      ManagedSubscription::ManagedSubscription(
        Action<BidAskResponse, bool>^ callback)
      {
        m_delegate = gcnew DelegateFunc(this, &ManagedSubscription::OnCallback);
        m_delegateHandle = System::Runtime::InteropServices::GCHandle::Alloc(m_delegate);
        m_nativeCallbackWrapper = new NativeCallbackWrapper(static_cast<CallbackPtr>(Marshal::GetFunctionPointerForDelegate(m_delegate).ToPointer()));
        m_callback = callback;
      }

bool ManagedSubscription::OnCallback(const std::vector<Sample>& result, bool disconnected)
  {
    try
    {
        m_callback(samplesData, disconnected);
        return true;
    }
    catch (Exception^ ex)
    {
      return false;
    }
    catch (Object^ ex)
    {
      return false;
    }
  }

  //This is given to natice class which actually calls this callback (ManagedSubscription::OnCallback mentioned above)
  const ManagedSubscription::Callback_t& ManagedSubscription::GetNativeCallback()
  {
    return m_nativeCallbackWrapper->m_callback;
  }

这是我的原生C ++代码:

bool Publish(const std::vector<SampleType>& samples, bool disconnected)
        {
          try
          {
            //This actually calls managed callback (ManagedSubscription::OnCallback)
            return m_subscriptionCallback(samples, disconnected);
          }
          catch (std::exception& e)
          {
            return false;
          }
          catch (...)
          {
            return false;
          }
        }

这是崩溃的堆栈痕迹:

KERNELBASE!RaiseException+68     cdb52105     00007ffb     00000001    
clr!RaiseTheExceptionInternalOnly+33b     cdee43f4     00007ffb     00000000    
clr!RaiseTheException+a4     cdee4460     00007ffb     00000002    
clr!RealCOMPlusThrow+69     cdeb6d72     00007ffb     43d60b70    
clr!Thread::RaiseCrossContextException+333     cdcd24cb     00007ffb     2fbadcf8    
clr!Thread::DoADCallBack+1a8     cdb69535     00007ffb     2fbade01    
clr!UM2MDoADCallBack+b3     cdb681dd     00007ffb     8a988a50    
clr!UMThunkStub+26d     bc090516     00007ffb     2fbaef70    
ManagedChartFeedInterface!DFS::Chart::HistoricalCache::TypedSubscription<DFS::Chart::ChartCache::ForexInstrumentInfo>::Publish+66 

第一行堆栈跟踪表示来自上述return m_subscriptionCallback(samples, disconnected);中的本机代码Publish的调用。

我在回调编组方面有什么不妥吗? 它是否与App-Domains相关,因为客户端应用程序使用了app-domain概念?

1 个答案:

答案 0 :(得分:0)

我在同一问题上从其他网站得到了安静的有用答案:我也想在这里分享一下。这是链接:

[https://msdn.microsoft.com/en-us/library/367eeye0.aspx][1]说没有必要固定代表;即使GC重新定位代理,函数指针仍将保持有效。

在CoreCLR来源中,在捕获到其他异常后,Thread::DoADCallBack仅通过Thread::RaiseCrossContextException宏调用END_DOMAIN_TRANSITIONThread::DoADCallback仅在应用程序域不匹配时才使用该宏。