天天看点

C++与C#互操作

1. C#调用C++ Dll

   主要通过PINVOKE调用导出函数,网上资料挺多的,本人也不是很精通,略过....

2. C++调用C# Library

   1). 方案1

       在C++工程属性里设置公共语言运行库支持(常规页面), 改变编译选项(http://technet.microsoft.com/zh-cn/library/ms235211(v=vs.90).aspx)

       然后再代码里动态载入C# library,创建(枚举)相关类型,调用方法

DWORD WINAPI LoadDotNetDll(LPVOID lpThreadParameter)
{
	CoInitialize(NULL);
	
	TCHAR buffer[MAX_PATH];
	GetModuleFileName(NULL,buffer,MAX_PATH);
	CString exeModuleName = buffer;
	int index = exeModuleName.ReverseFind(_T('\\'));
	CString dllName = exeModuleName.Left(index+1)+_T("CSAlarmLib.dll");

	String^ strDllName = gcnew String((LPCTSTR)dllName);
	Assembly^ dllModule = Assembly::LoadFile(strDllName);

	//遍历Assembly里类
	String^ typeName = gcnew String(_T("CSAlarmLib.AlarmCenter"));

	Type^ type = dllModule->GetType(typeName);
	System::Object^ obj = dllModule->CreateInstance(typeName,TRUE);

	::OutputDebugString((LPCTSTR)CString(obj->ToString()));

	//遍历AlarmCenter方法
	String^ strMethod = gcnew String(_T("OnStart"));
	MethodInfo^ method = type->GetMethod(strMethod);

	array<Object^>^ myArray = gcnew array<Object^>(1){gcnew AtlTrayHost::TrayHost()};
	AtlTrayHost::TrayHost^ trayHost = gcnew AtlTrayHost::TrayHost();
	//myArray->Insert(0,trayHost);
	method->Invoke(obj, myArray);

	return 0;
}
           

C++/cli支持在代码中直接链接C# library, 使用编译指令#using,示例代码如下

using namespace System;
#using "JieKouLib.dll"
using namespace JieKouLib;

namespace AtlTrayHost {

	/// <summary>
	/// ClrCls 摘要
	/// </summary>
	public ref class TrayHost : public ITrayHost
	{
	public:
		virtual void OnReceive(String^ strXml)
		{
			::OutputDebugString((LPCTSTR)CString(strXml));
		}
	};
}
           

2)提供Com接口函数,编写C# Com library, 可以采用如下方法编写、

   a. 编写Atl Com Dll,添加IDL接口及连接点接口,编译注册,若不注册,则无法将tlb添加进C#引用

   b. 创建C# Library,将tlb导入至C#工程

   c. 将接口拷贝至新的文件,删除不必要的属性

//IAgentTrayPlugin.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TrayPluginLib
{
    [Guid("D3BF29BC-A706-430B-AAB4-9D9DE6BCD861")]
    [InterfaceType(1)]
    public interface IAgentTrayPlugin
    {
        void Send(string bstrXml);
    }
}


//IAgentTrayPluginEvents.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace TrayPluginLib
{
    public delegate void Receive(string bstrXml);

    [InterfaceType(1)]
    [Guid("6330974C-E92C-4E49-8AC8-7F756DE23A33")]
    public interface _IAgentTrayPluginEvents
    {
        void OnReceive(string bstrXml);
    }
}
           

d. 创建Com对象

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using TrayPluginLib;

namespace AlarmCenterLib
{
    [Guid("3D1FC18A-D2C2-40BF-8B1E-A29B428A78E6"),
    ComSourceInterfaces(typeof(_IAgentTrayPluginEvents))]
    public class AlarmCenterPlugin : IAgentTrayPlugin
    {
        public event Receive OnReceive;

        public void Send(string bstrXml)
        {
            if (OnReceive!=null)
            {
                OnReceive(bstrXml);
            }
        }
    }
}
           

e. c++代码中创建Com对象