C#应用程序中的C ++ lib RTTI

时间:2010-04-27 13:36:36

标签: c# c++ rtti

我正在开发使用c ++ lib文件的C#游戏编辑器。 我想在C#中使用RTTI for C ++类。 是否有可能在C#中获得C ++类的RTTI? 如果是的话怎么样?

2 个答案:

答案 0 :(得分:4)

您无法直接向.NET平台公开本机C ++类型或代码。

然而,有三种方式与“原生”C&来自.NET的C ++代码(在C#,VB.Net或其他任何方面)。

  1. COM
  2. P /调用
  3. CLI / C ++
  4. COM可能是.NET方面最容易使用的。只需将COM对象添加到.NET项目作为参考,然后开始与接口和类进行交互。有关使用.NET在COM中进行交互的更多详细信息,请阅读如下所示的书:

    .NET and COM: The Complete Interoperability Guide http://ecx.images-amazon.com/images/I/51UsCPeI%2BAL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU01_.jpg

    http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X

    这当然要求您将游戏引擎对象公开为COM对象。这不重要。

    下一个最容易使用的是P / Invoke。如果您的游戏代码打包在带有C调用约定的标准Windows DLL中,则可以使用P / Invoke访问该DLL中的函数。例如:

    public static class UserDll
    {
        [DllImport("user32.dll")]
        private static extern bool FlashWindow(IntPtr hwnd, bool bInvert);
    
        public static void FlashWindow(System.Windows.Forms.Form window)
        {
            FlashWindow(window.Handle, false);
        }
    }
    

    你可以用P / Invoke做很多事情。甚至让你的C / C ++代码回调到带有代表的C#,而不是。

    我过去已经构建了游戏引擎工具,它们使用P / Invoke来调用DLL中公开的函数。您只需要小心管理本机资源。这里的IDisposable界面和类终结器成为你的朋友。例如:

    public class Player : IDisposable
    {
        private IntPtr _thePlayer;
    
        public Player()
        {
            _thePlayer = CreatePlayer();
        }
    
        ~Player()
        {
            Dispose(false);
        }
    
        public void Dispose()
        {
            Dispose(true);
        }
    
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
               // dispose of managed objects (ie, not native resources only)
            }
    
            if (_thePlayer != IntPtr.Empty)
            {
                DestroyPlayer(_thePlayer);
                _thePlayer = IntPtr.Empty;
            }
        }
    
        [DllImport("gameengine.dll")]
        private static extern IntPtr CreatePlayer();
    
        [DllImport("gameengine.dll")]
        private static extern void DestroyPlayer(IntPtr player);
    }
    

    使用P / Invoke有一个缺点。首先,它可以为本机调用添加一个重要的编组开销(尽管有一些方法可以加快速度)。它还需要gameengine.dll中的C API。如果您的引擎是C ++类,则必须为C ++类提供C API。这可以添加大量工作(或需要代码生成器)。

    我不打算详细介绍处理与本机代码进行编组管理对象/数据的所有混乱细节。只知道它可以完成,MSDN就是你的朋友。

    将本机C ++代码暴露给.NET的第三种也许是最好的方法是通过CLI / C ++混合模式程序集。 CLI / C ++允许您在单个程序集中无缝地混合本机代码和托管代码。

    CLI / C ++有一个有趣的语法,但如果你是一个C ++程序员,它就不难适应。一个例子可能是这样的:

    using namespace System;
    
    // CLI/C++ "managed" interface 
    interface class IDog
    {
        void Bark();
    };
    
    #pragma managed(push off)
    
    // Native C++
    class Pet
    {
    public:
       Pet() {}
       ~Pet() {}
    
       const char* GetNativeTypeName()
       {
           return typeid(Pet).name();
       }
    };
    
    #pragma managed(pop)
    
    // CLI/C++ "managed" class
    ref class Dog : IDog
    {
    private:
        Pet* _nativePet;
    
    public:
        Dog()
          : _nativePet(new Pet())
        {}
        ~Dog()
        {
            delete _nativePet; 
            _nativePet = 0;
        }
    
        void Bark()
        {
            // Managed code talking to native code, cats & dogs living together, oh my!
            Console::WriteLine("Bow wow wow!");
    
            Console::WriteLine(new System::String(_nativePet->GetNativeTypeName()));
        }
    };
    
    void _tmain()
    {
        Dog^ d = gcnew Dog();
        d->Bark();
    }
    

    我的建议(完全按照你要做的那样)是因为除了中等复杂之外,最好的解决方案是尝试为游戏引擎提供CLI / C ++ API。我从MSDN中学到了关于CLI / C ++所需要知道的一切,但是如果你喜欢内容丰富,我会听到这本书很好。

    Expert Visual C++/CLI: .NET for Visual C++ Programmers http://ecx.images-amazon.com/images/I/51iAp1TIXgL._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA300_SH20_OU01_.jpg

    http://www.amazon.com/Expert-Visual-CLI-Programmers-Experts/dp/1590597567

答案 1 :(得分:1)

This article描述了这个过程。

  

运行时类型标识(RTTI)允许在程序执行期间确定对象的类型。 C#包括三个支持运行时类型标识的关键字:is,as和typeof。

使用is来确定某个对象是否属于您想要的类型:

if (myVariable is string)
{
     // do stuff
}

您使用as将一个对象转换为另一个对象。如果不存在转换,则返回null

string myString = myVariable as string;
if (myString != null)
{
    // do stuff
}

您使用typeof获取有关类型的信息。

  

要获取表达式的运行时类型,可以使用.NET Framework方法GetType