C++调用C#之C++DLL调用C# COM控件

1. 新建项目

这里我们使用ATL,来接受C# COM控件向外发送的事件。

2. 初始化ATL

#include "stdafx.h"

CComModule _module;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		{
			_module.Init(NULL, hModule);//初始化
		}
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		{
			_module.Term();//释放
		}
		break;
	}
	return TRUE;
}

 3. 定义一个显示UI的接口类

IShowUI.h

#ifdef DLL_SHOW_UI
#define DLL_CLASS _declspec(dllimport)
#else
#define DLL_CLASS _declspec(dllexport)
#endif

#ifndef _ISHOW_UI_H_
#define _ISHOW_UI_H_

#include <functional>
#include <atlconv.h>

using std::function;

class DLL_CLASS IShowUI
{
protected:
	IShowUI();

	virtual ~IShowUI();

public:
	static IShowUI* CreateInstance();

	static void DestoryInstance(IShowUI* pIShowUI);

public:
	virtual void SetCallback(function<void(BSTR)>* pCallback) = 0;

	virtual void ShowDialog(BSTR bstrDialogType, BSTR bstrParam) = 0;
};

#endif

IShowUI.cpp

#include "IShowUI.h"
#include "ShowUIImpl.h"

IShowUI::IShowUI()
{

}

IShowUI::~IShowUI()
{

}

IShowUI* IShowUI::CreateInstance()
{
	IShowUI* pIShowUI = new CShowUIImpl;
	return pIShowUI;
}

void IShowUI::DestoryInstance(IShowUI* pIShowUI)
{
	if (pIShowUI)
	{
		delete pIShowUI;
	}
}

 4. 定义一个显示UI的实现类

ShowUIImpl.h

#ifndef _SHOW_UI_IMPL_H_
#define _SHOW_UI_IMPL_H_

#include "IShowUI.h"
#ifdef _DEBUG
#import "../NetActiveX/bin/Debug/NetActiveX.tlb"
#else
#import "../NetActiveX/bin/Release/NetActiveX.tlb"
#endif

class CHandleEvent;

class CShowUIImpl : public IShowUI
{
public:
	CShowUIImpl();

	virtual ~CShowUIImpl();

public:
	virtual void SetCallback(function<void(BSTR)>* pCallback);

	virtual void ShowDialog(BSTR bstrDialogType, BSTR bstrParam);

private:
	function<void(BSTR)>* m_pCallback;
	CHandleEvent* m_pHandleEvent;
	NetActiveX::IShowDialogPtr m_showDialogPtr;
};

#endif

ShowUIImpl.cpp

#include "stdafx.h"
#include "IShowUI.h"
#include "ShowUIImpl.h"
#include "SystemString.h"
#include <atlcom.h>

//处理C# COM控件发送的事件
class CHandleEvent : public IDispEventImpl<0,
	CHandleEvent,
	&(__uuidof(NetActiveX::IEvent)),
	&(__uuidof(NetActiveX::__NetActiveX)),
	1,
	0>
{
public:
	CHandleEvent()
	{
		m_pCallback = NULL;
	}

	void SetEventCallback(std::function<void(BSTR)>* pCallback)
	{
		m_pCallback = pCallback;
	}

	STDMETHOD(NotifyEvent)(BSTR bstr)
	{
		if (m_pCallback)
		{
			(*m_pCallback)(bstr);
		}
		return S_OK;
	}

	BEGIN_SINK_MAP(CHandleEvent)
		SINK_ENTRY_EX(0, (__uuidof(NetActiveX::IEvent)), 20, NotifyEvent)//事件处理函数,此处的事件ID=20必须和C# NotifyEvent定义的完全一样
	END_SINK_MAP()

private:
	function<void(BSTR)>* m_pCallback;//事件处理回调函数
};

CShowUIImpl::CShowUIImpl()
{
	CoInitialize(NULL);
	m_pCallback = NULL;
	m_pHandleEvent = new CHandleEvent;
	m_showDialogPtr = NetActiveX::IShowDialogPtr(__uuidof(NetActiveX::ShowDialogImpl));
}

CShowUIImpl::~CShowUIImpl()
{
	delete m_pHandleEvent;
	m_pHandleEvent = NULL;
	CoUninitialize();
}

void CShowUIImpl::SetCallback(function<void(BSTR)>* pCallback)
{
	m_pCallback = pCallback;
}

void CShowUIImpl::ShowDialog(BSTR bstrDialogType, BSTR bstrParam)
{
	if (m_showDialogPtr.GetInterfacePtr())
	{
		CSystemString strDialogType(bstrDialogType);
		CSystemString strParam(bstrParam);

		m_pHandleEvent->SetEventCallback(m_pCallback);//设置事件处理回调函数
		m_pHandleEvent->DispEventAdvise(m_showDialogPtr);//注册事件
		m_showDialogPtr->ShowDialog(strDialogType.GetBSTR(), strParam.GetBSTR());
		m_pHandleEvent->DispEventUnadvise(m_showDialogPtr);//取消事件
	}
}


 5. 其他辅助类

SystemString.h

#ifndef _SYSTEM_STRING_H_
#define _SYSTEM_STRING_H_

class CSystemString
{
public:
	explicit CSystemString(BSTR bstr)
	{
		if (bstr)
		{
			m_bstr = SysAllocString(bstr);
		}
		else
		{
			m_bstr = NULL;
		}
	}

	~CSystemString()
	{
		Clear();
	}

	void Clear()
	{
		if (m_bstr)
		{
			SysFreeString(m_bstr);
			m_bstr = NULL;
		}
	}

	BSTR GetBSTR() {return m_bstr;}

private:
	CSystemString(CSystemString&);
	CSystemString& operator =(CSystemString&);

private:
	BSTR m_bstr;
};

#endif


6. 新建一个C++ win32控制台应用程序,调用DLL显示C#对话框

#include "stdafx.h"
#include <string>
#include <functional>
#define DLL_SHOW_UI
#include "IShowUI.h"

using std::string;
using std::wstring;

#pragma comment(lib, "DllInterface.lib")

class EmployeeData
{
public:
	void ParseString(wstring s)
	{
		int beg = -1;
		int end = -1;

		beg = 0;
		end = s.find(L",", beg);
		if (end != -1)
		{
			m_name = s.substr(beg, end - beg);
			beg = end + 1;
		}
		end = s.find(L",", beg);
		if (end != -1)
		{
			m_sex = s.substr(beg, end - beg);
			beg = end + 1;
		}
		end = s.find(L",", beg);
		if (end != -1)
		{
			m_age = _wtoi(s.substr(beg, end - beg).c_str());
			beg = end + 1;
		}
		end = s.find(L",", beg);
		if (end != -1)
		{
			m_phone = s.substr(beg, end - beg);
			beg = end + 1;
		}
		end = s.length();
		if (beg < end)
		{
			m_mobile = s.substr(beg, end - beg);
		}
	}

	wstring ToString()
	{
		wstring s = L"";
		wchar_t psz[32] = {0};

		s += m_name;
		s = s + L"," + m_sex;
		s = s + L"," + _itow(m_age, psz, 10);
		s = s + L"," + m_phone;
		s = s + L"," + m_mobile;

		return s;
	}

	wstring m_name;
	wstring m_sex;
	int m_age;
	wstring m_phone;
	wstring m_mobile;
};

void Callback(BSTR bstr)
{
	EmployeeData employee;

	employee.ParseString(bstr);
}

int _tmain(int argc, _TCHAR* argv[])
{
	IShowUI* pShowUI = IShowUI::CreateInstance();
	EmployeeData employee;
	function<void(BSTR)> call = std::bind(&Callback, std::tr1::placeholders::_1);

	employee.m_name = L"123";
	employee.m_sex = L"男";
	employee.m_age = 10;
	employee.m_phone = L"123456";
	employee.m_mobile = L"13245678952";

	BSTR bstr = L"EmployeeDialog";
	wstring s = employee.ToString();
	BSTR bstrParam = (BSTR)s.c_str();

	pShowUI->SetCallback(&call);//设置事件响应回调
	pShowUI->ShowDialog(bstr, bstrParam);//显示员工属性对话框

	IShowUI::DestoryInstance(pShowUI);
	pShowUI = NULL;

	return 0;
}



 

原文地址:https://www.cnblogs.com/dongc/p/5225115.html