C# C++混用的一些心得

最近在做个服务端的项目,由于客户端是用C#写的,考虑到代码重用性,决定服务端的也用c#写。查了些资料,没有发现应用级别的c#通讯库,特别是用IOCP的。都是些简单的demo。为了开发速度和代码的健壮,所以决定用boost的asio库做通讯底层。这自然就涉及到c++与c#的混用问题了。

比较好的方法是将c++ 或 c#的代码封装成dll供另外一个语言调用。由于c#是处理上层逻辑的,会不断的拓展功能,属于框架性质,且直观上应该是逻辑调用通讯的功能,故而决定将c++端封装成dll。

问题来了:通讯底层是居于事件模式的。譬如OnAcceptor OnReceive 事件,这种模式要求在事件中调用响应事件的代码。而一般这些响应代码是属于逻辑层的事情。所以这要求c++调用c#的代码(dll)。由于暂时找不到在 非托管c++中创建托管类,并调用托管类的函数 的方法。所以只能消耗一些效率,做个中间层,将事件模式改为轮询模式。

看来得好好研究下CLR Interop技术了。

 

 

附 托管代码下要调试非托管的dll 得把调试选项的非托管代码给勾上。

 

===============================================================

非托管c++中调用c#的代码的方法已经查到。总的来说是将托管函数封装成委托,再通过 Marshal.GetFunctionPointerForDelegate 将委托转换成非托管的函数指针就行了。

 

代码
/// <summary>
/// 逻辑连接的操作委托
/// </summary>
 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] //c#与 非托管c++的传参方式不一样。故加这行统一。
unsafe public delegate bool DG_LogeConnectOperator(Byte* pBuf, UInt32 nLen, UInt32 Par);

 

 

代码
public class TestTCPConnect : LogeConnect
{
#region 公共函数
public TestTCPConnect(UInt32 hd)
:
base(hd)
{
unsafe
{
dgLogeConnectOperator
= new DG_LogeConnectOperator(this.LogeConnectOperator);
}
pLogeConnectOperator
= Marshal.GetFunctionPointerForDelegate(dgLogeConnectOperator);
BindLogeConnectOperator(pLogeConnectOperator);//将函数指针传递给非托管代码,使其可以被调用
}



/// <summary>
/// 逻辑连接的操作
/// </summary>
/// <param name="pBuf">为缓冲区</param>
/// <param name="nLen">缓冲区长度</param>
/// <param name="Par">拓展使用</param>
/// <returns></returns>
unsafe public override bool LogeConnectOperator(Byte* pBuf, uint nLen, uint op)
{
       return false;
}
#endregion

#region 成员变量


#region 逻辑连接的操作委托
private DG_LogeConnectOperator dgLogeConnectOperator = null;
private IntPtr pLogeConnectOperator = IntPtr.Zero;
#endregion

#endregion
}

 

需要指出的是 上面的委托是针对类的每一个实例的,故而相对应的函数指针 也对应到每一个实例。

可以通过静态函数与委托的方式 对应一个唯一的函数指针。

注意委托与函数指针的生存时间。上例中 dgLogeConnectOperator 与 pLogeConnectOperator 没有被垃圾回收 才能保证函数指针有效。

posted @ 2010-09-08 15:56  迷花倚石忽已暝  阅读(1046)  评论(0编辑  收藏  举报