zoukankan      html  css  js  c++  java
  • 利用C++/CLI 封装Native C++ 提升.NET web game性能

    利用C++/CLI 封装Native C++ 提升.NET web game性能

       

    这段时间在做新项目的技术论证,其基本想法就是利用Flex调用远程WCF以及发送Socket请求,来实现远程通信,WCF负责实时性要求不高的操作,如聊天,邮件,交易,买卖等,而Socket的目的是提供实时战斗的服务。

    无论是WCF,还是Socket,都会提供不少的游戏逻辑,当然,大家心里都有数,与C++相比C#在纯数值运算上慢的太多,但是提到语法简洁性,MS的数据访问组件支持,IDE的智能感知VC又相形见绌。

    虽然C++/CLI不能够满足上面的各种要求,但是它却可以Native C++C#Adapter,来保证程序的优质性。本文的目的有两点:

             如何利用C++/CLI封装Native C++,并被C#调用

             被封装过的Native C++代码与C#代码在性能方面的对比

    1. C++/CLI封装Native C++,并被C#调用

      为了方便团队开发,我们通常要将C++代码编译成DLL,以方便.NET开发人员调用,因此,我们首先来编写一个Native C++的类,并编译成DLL。过程如下:

      1. VS2008VC++项目模板中,选择Win32项目中的 Win32 Project,并命名为NativeCPPDLL,如下图所示:

      2. 选择将其编译成DLL,如下图所示:

      3. 在项目中添加一个名为NativeCPP的类,基类结构如下图所示:

      4. NativeCPP的头文件(NativeCPP.h)代码如下:

        #pragma once

        #include "math.h"

        #ifndef GoWin_DLL_CLASS_EXPORTS

            //该类可导出

            #define GoWin_DLL_CLASS __declspec(dllexport)

        #else

            //该类可导入

            #define GoWin_DLL_CLASS __declspec(dllimport)

        #endif

           

        class GoWin_DLL_CLASS NativeCPP

        {

        public:

                      NativeCPP(void);

                      ~NativeCPP(void);

                      void Compute1();

                      void Compute2();

        }

      5. NativeCPPCPP文件(NativeCPP.cpp)的代码如下所示:

        #include "StdAfx.h"

        #include "NativeCPP.h"

           

        NativeCPP::NativeCPP(void)

        {

        }

           

        NativeCPP::~NativeCPP(void)

        {

        }

        void NativeCPP::Compute1 ()

        {

        for(int i=0;i<100000;i++)

        {

           for(int j=0;j<i;j++)

           {

           

           }

        }

        }

        void NativeCPP::Compute2 ()

        {

        for(int i=0;i< 30000000;i++)

        {

           pow(1.05,i);//pow函数是游戏里常用的数据增长公式

        }

        }

       

    1. 编译代码。
    2. 在解决方案中添加一个C++/CLI的类库,将命名为CPPWrapper如下图所示:

       

       

    3. CPPWrapper添加刚才编译好的DLL项目的引用,如下图所示,在该项目上点击右键,选择"Reference":

       

    4. 在弹出的对话框中选择Add New Reference,如下图所示:

       

       

    5. Projects里选择刚才建立的NativeCPPDLL项目。如下图所示:

       

       

    6. CPPWrapper里添加一个头文件,内容和名称都"NativeCPP.h"一样。
    7. CPPWrapper里添加一个名为NativeCPPWrapper的托管类,如下图所示:

      该类的结构与NativeCPP中的类结构完全一样,但是要在类中定义一个从DLL导入的Native C++类的指针,.h文件中的代码如下所示:

      #pragma once

      #include "NativeCPP.h"

      #define GoWin_DLL_CLASS_EXPORTS

      public ref class NativeCPPWrapper

      {

      private:

         NativeCPP*nativeCPP;//native c++类的指针

      public:

         NativeCPPWrapper(void);

      public:

         void Compute1();

         void Compute2();

      };

       

    该类的CPP文件,完成就是对Native C++类的接口转换,其代码如下所示:

    #include "StdAfx.h"

    #include "NativeCPPWrapper.h"

       

    NativeCPPWrapper::NativeCPPWrapper(void)

    {

                  this->nativeCPP =new NativeCPP();

    }

    void NativeCPPWrapper::Compute1()

    {

                  this->nativeCPP ->Compute1 ();

    }

    void NativeCPPWrapper::Compute2()

    {

                  this->nativeCPP ->Compute2 ();

    }

    1. C++/CLI的项目属性里,将Common Language Runtime Support设置为Common Language Runtime Support(/clr),否则的话,将无法使用非托管的Native C++

       

    2. 现在可以建立一个C#的项目了,只要添加CPPWrapper的引用,就可以像调用C#写的DLL一样来调用C++/CLI写的类了,如下图所示:

    3. 如何你用的是64位的操作系统的话,直接调用会出错,这时要配置一个C#项目的编译选择,将编译的目标平台设置成"X86"。(请千万别把它读成"叉儿八六",你是专业计算机人员,应该说的专业点,它叫"艾克思八六")。如下图所示:

       

       

    1. 前面对如何利用C++/CLI封装原生C++代码,并被C#所调用作了一些说明,下面通过数据对比来说明这样做的意义。
      1. 实验说明:

    该实验将进行如下几组测试

    编号

    说明

    1

    利用MFC调用NativeCPP DLL,并分别测试NativeCppCompute1()以及Compute2()两个函数所需要的时间

    2

    利用C# WinForm调用NativeCPPWrapperC++/CLI)来间接访问NativeCPP类中的Compute1()以及Compute2()两个函数,并检测所需要的时间。

    3

    利用C# WinForm直接调用C#编写的相同功能的Compute1()以及Compute2()两个函数,并检测所需要的时间。

    说明:Compute1()里只有循环,Compute2()里包括了一个pow函数。

    1. 代码略
    2. 测试环境

    3. 测试结果(Debug版本)

    编号

    操作

    时间

    1

    MFC 调用NativeCPP::Compute1()

    14s

    2

    MFC调用NativeCPP::Compute2()

    9s

    3

    C#调用NativeCPPWrapper::Compute1()

    14s

    4

    C#调用NativeCPPWrapper::Compute2()

    9s

    5

    C#调用C#写的Compute1()

    19s

    6

    C#调用C#写的Compute2()

    3s

    1. 结论

    通过1234的数据,不难发现,利用C++/CLI封装过的Native C++在性能上基本没有什么损失(但是一定要在操作密集中的代码中封装,而不是调用密集型的代码)。135三组数据可说明,在单纯的循环上,C#要比C++慢很多。

    debug模式下大量使用Pow函数的时候.net framework里提供的Math.Pow,要远远快于math.h中的pow函数,实验结果中几乎差了三倍!如果改成Release模式,C++中两函数的操作时间基本上都为0,当然C#的速度也有明显提高,但是要远远慢于C++

  • 相关阅读:
    SPOJ
    基础计算几何
    数颜色
    Codeforces 986B
    一些有趣的题
    jQuery
    linux命令学习
    javaScript
    css
    html
  • 原文地址:https://www.cnblogs.com/warensoft/p/1680290.html
Copyright © 2011-2022 走看看