У меня есть метод, который регистрирует функции и интерфейс на C ++, и я использую CoMarshalInterThreadInterfaceInStream для маршалинга указателя интерфейса на метод в другом потоке.

В RegisterFunction:

HRESULT hr = CoMarshalInterThreadInterfaceInStream(IID_Function, function, &stream);

Выпустив его через GetFunction:

HRESULT hr = CoGetInterfaceAndReleaseStream(stream, IID_Function, reinterpret_cast<void**>(&function));

Поскольку я буду вызывать GetFunction более одного раза, а CoGetInterfaceAndReleaseStream освобождает поток только один раз, как мне сохранить поток, чтобы использовать его снова?


Я пробовал использовать IGlobalInterfaceTable, но не могу заставить его работать.

Я успешно зарегистрировал интерфейс в RegisterFunction:

DWORD dwCookie = 0;
int a = 0;
if (pGIT == NULL) {
  HRESULT hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
     NULL,
     CLSCTX_INPROC_SERVER,
     IID_IGlobalInterfaceTable,
     (void **)&pGIT);
  if (hr != S_OK) {
     throw _com_error(hr);
  }
}

if (dwCookie == 0) {
  HRESULT hr = pGIT->RegisterInterfaceInGlobal(function, IID_Function, &dwCookie);
  if (hr != S_OK) {
     throw _com_error(hr);
  }
}

Но когда я попытался получить его в GetFunction:

   IGlobalInterfaceTable* GIT = NULL;
      if (GIT == NULL) {
         hr = CoCreateInstance(CLSID_StdGlobalInterfaceTable,
            NULL,
            CLSCTX_INPROC_SERVER,
            IID_IGlobalInterfaceTable,
            (void **)&GIT);
         if (FAILED(hr)) {
            exit(0);
         }
      }

      hr = pGIT->GetInterfaceFromGlobal(dwCookie, IID_Function, (void**)&function);
      if (FAILED(hr)) {
            exit(0);
      }

Я получаю HR-ошибку invalidArg при попытке RegisterInterfaceInGlobal (даже если он использует тот же параметр, что и CoMarshalInterThreadInterfaceInStream, за исключением файла cookie)

2
user3910703 2 Янв 2018 в 21:01

2 ответа

Лучший ответ

Как заявил Соронель Хэтир, вы не можете сделать это с помощью CoMarshalInterThreadInterfaceInStream. Он может (де) маршалировать интерфейс только один раз.

Попробуйте вместо этого использовать IGlobalInterfaceTable. Вы можете зарегистрировать свой COM-объект в таблице один раз, а затем извлекать объект из таблицы в любом потоке / квартире столько раз, сколько захотите, пока вы не отзовете объект из таблицы.

3
Remy Lebeau 9 Янв 2018 в 23:34

Вы не можете сделать это с CoMarshalInterThreadInterfaceInStream, это удобный метод для указателей интерфейса, который будет извлечен только один раз.

Вместо этого используйте CoMarshalInterface / CoUnmarshalInterface и используйте поток, созданный с помощью ShCreateMemStream.

0
SoronelHaetir 2 Янв 2018 в 18:37