2016-11-17 2 views
0

Я искал в Интернете решение следующей проблемы, но не могу обернуться вокруг него.Отправка обратного вызова C++ для .NET C++/CLI Wrapper

У нас есть большое монолитное приложение med в C++. Чтобы «обновить» его в новом мире, мы вставляем представления WPF в него, сгенерированные в управляемой оболочке C++/CLI. Первоначальный вызов выполняется из C++ с помощью smartpointer.

 if (SUCCEEDED(ptr.CreateInstance(__uuidof(CloudServices)))) 
    { 
     CRect rect; 
     pWndContainer->GetWindowRect(rect); 

     ptr->InitializeControl((LONG)pWndContainer->GetSafeHwnd(), ID_AIS_BALANCEMATRIX, bstr.m_str, rect.Width(), rect.Height()); 
    } 

А в классе обертке интерфейс объявлен как

interface ICloudServices : IDispatch{ 
[id(1)] HRESULT InitializeControl([in] LONG hWndParent, [in] LONG controlTypeId, [in] BSTR parameters, [in] LONG width, [in] LONG height); 

И реализуется, как это в обертку

STDMETHODIMP CCloudServices::InitializeControl(LONG hWndParent, LONG controlTypeId, BSTR parameters, LONG width, LONG height) { ... } 

Проблема: Все отлично и МОФ работы представление отображается в приложении C++. Теперь нам нужно отправить информацию обратно на C++ из .NET-кода.

Как я могу отправить неуправляемую функцию обратного вызова в оболочку в качестве аргумента InitializeControl и как ее использовать/преобразовать в соответствующий делегат .net?

See desired solution schematic

+0

Код C++ реализует COM-сервер. Обратный вызов - это * событие *, [добавить точку подключения] (https://msdn.microsoft.com/en-us/library/7bkz4x17.aspx). –

+0

Спасибо за ваше правильное предложение. Я видел, как сделать реализацию на управляемой стороне, но как я могу использовать это событие в C++? У вас есть пример, который соответствует представленной мной схеме? –

ответ

0

Мы, кажется, не найти работающее решение этой проблемы, поэтому мы в конечном итоге с отправкой информации обратно с помощью WM_DATACOMPY. Не самый эффективный способ, но он работает.

public void SendCommand(Command command) 
    { 
     // Find the target window handle. 
     IntPtr hTargetWnd = NativeMethod.FindWindow("OurAppNameInCpp", null); 
     if (hTargetWnd == IntPtr.Zero) 
     { 
      throw new Exception("Sending '{0}'. Unable to find the \"OurAppNameInCpp\" window".Args(command.AsXmlMessage)); 
     } 

     // Prepare the COPYDATASTRUCT struct with the data to be sent. 
     MyStruct myStruct; 

     myStruct.Message = command.AsXmlMessage; 

     // Marshal the managed struct to a native block of memory. 
     int myStructSize = Marshal.SizeOf(myStruct); 
     IntPtr pMyStruct = Marshal.AllocHGlobal(myStructSize); 
     try 
     { 
      Marshal.StructureToPtr(myStruct, pMyStruct, true); 

      COPYDATASTRUCT cds = new COPYDATASTRUCT(); 
      cds.cbData = myStruct.Message.Length + 1; 
      cds.lpData = Marshal.StringToHGlobalAnsi(myStruct.Message); 

      // Send the COPYDATASTRUCT struct through the WM_COPYDATA message to 
      // the receiving window. (The application must use SendMessage, 
      // instead of PostMessage to send WM_COPYDATA because the receiving 
      // application must accept while it is guaranteed to be valid.) 
      NativeMethod.SendMessage(hTargetWnd, WM_COPYDATA, IntPtr.Zero, ref cds); 

      int result = Marshal.GetLastWin32Error(); 
      if (result != 0) 
       throw new Exception("SendMessage(WM_COPYDATA) failed w/err 0x{0:X}".Args(result)); 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(pMyStruct); 
     } 
    } 
Смежные вопросы