У меня есть следующая настройка теста, написанная в Visual Studio 2015 и использующая Windows SDK 7.1:
- C # проект (TestCs) с атрибутами COM.Он предоставляет метод Run и вызывает событие NotifyEvent
- C ++ DirectShow filter (TestFilter).Он построен на примере TransInPlace и содержит TestCs
- C ++ Console Application (TestApp).Он просто загружает TestFilter
При компиляции в Debug и запуске тестового приложения, функциональность, кажется, работает, и событие обрабатывается, как и ожидалось.Проблема в том, что приложение вылетает при выходе, и до сих пор мне не удалось понять, почему.Буду очень признателен за помощь здесь.
А теперь для деталей: Приложение выглядит так:
#include <windows.h>
#include <initguid.h>
#include <atlbase.h>
#include <streams.h>
// {E705C8D3-EE60-4012-9E83-3CFE4A11D1B5}
DEFINE_GUID(CLSID_TestFilter,
0xe705c8d3, 0xee60, 0x4012, 0x9e, 0x83, 0x3c, 0xfe, 0x4a, 0x11, 0xd1, 0xb5);
void Test()
{
CComPtr<IBaseFilter> pFilter;
HRESULT hr = CoCreateInstance(CLSID_TestFilter, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void **)&pFilter);
if (FAILED(hr))
return;
}
void main()
{
CoInitialize(NULL);
Test();
CoUninitialize();
}
Сбой происходит при выходе из области действия основной функции, и я не могуполучить что-нибудь из стека вызовов.
Для теста CS определен следующий интерфейс
using System;
using System.Runtime.InteropServices;
namespace TestCs
{
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IFireTestCsEvents
{
[DispId(1)]
void NotifyEvent(string message);
}
public delegate void NotifyEventEventHandler(string message);
public interface ITestCs : IDisposable
{
event NotifyEventEventHandler NotifyEvent;
bool Run(string fileName);
void Close();
}
}
Это реализация интерфейса
using System.Runtime.InteropServices;
namespace TestCs
{
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(IFireTestCsEvents))]
public class TestCsImp : ITestCs
{
public event NotifyEventEventHandler NotifyEvent;
public TestCsImp()
{
}
public bool Run(string fileName)
{
NotifyEvent?.Invoke(fileName);
return true;
}
public void Close()
{
}
public void Dispose()
{
Close();
}
}
}
Что касается TestFilter, то оноснован на классе TransInPlace и добавлении объекта TestCsWrapper к хосту TestCs. Это заголовочный файл
#pragma once
#import "TestCs.tlb"
using namespace TestCs;
class TestCsWrapper :
public IDispEventSimpleImpl<1, TestCsWrapper, &__uuidof(IFireTestCsEvents)>
{
public:
BEGIN_SINK_MAP(TestCsWrapper)
SINK_ENTRY_INFO(1, __uuidof(IFireTestCsEvents), 0x1, HandleEvent, &NotifyEvent)
END_SINK_MAP()
void __stdcall HandleEvent(BSTR message);
public:
TestCsWrapper();
virtual ~TestCsWrapper();
bool Open();
void Close();
bool IsValid();
bool Load(const wchar_t *fileName);
private:
ITestCsPtr m_pTestCs;
static _ATL_FUNC_INFO NotifyEvent;
};
И это реализация
#include "Pch.h"
#include "TestCsWrapper.h"
_ATL_FUNC_INFO TestCsWrapper::NotifyEvent = { CC_STDCALL, VT_EMPTY, 1, { VT_BSTR } };
#define CREATE_CRASH
void __stdcall TestCsWrapper::HandleEvent(BSTR message)
{
::SysFreeString(message);
}
TestCsWrapper::TestCsWrapper()
{
}
TestCsWrapper::~TestCsWrapper()
{
Close();
}
bool TestCsWrapper::Open()
{
m_pTestCs = ITestCsPtr(__uuidof(TestCsImp));
if(!IsValid())
return false;
#ifdef CREATE_CRASH
DispEventAdvise(m_pTestCs);
#endif
return true;
}
void TestCsWrapper::Close()
{
if(IsValid())
{
#ifdef CREATE_CRASH
DispEventUnadvise(m_pTestCs);
#endif
m_pTestCs->Close();
m_pTestCs->Release();
m_pTestCs.Detach();
}
}
bool TestCsWrapper::IsValid()
{
return (m_pTestCs != NULL);
}
bool TestCsWrapper::Load(const wchar_t *fileName)
{
if(!IsValid())
return false;
BSTR bstr = ::SysAllocString(fileName);
VARIANT_BOOL success = m_pTestCs->Run(bstr);
::SysFreeString(bstr);
return success == VARIANT_TRUE;
}
Когда я отключил код DispEventAdvise, приложение закрываетсябез каких-либо исключений.
В вызов фильтра CreateInstance я добавил следующий код
bool TestFilter::Open()
{
if (!m_testCs.Open())
return false;
m_testCs.Load(L"some messsage");
return true;
}
Для демонстрации этого доступен полный код решения Visual Studio, который при необходимости может быть предоставлен
Надеюсь узнать, что я делаю не так.Спасибо