C ++ lib RTTI in C # application

I am developing a C # game editor that uses C ++ lib files. I want RTTI for C ++ classes in C #. Is it possible to get the RTTI of a C ++ class in C #? If so, how?

+2


a source to share


2 answers


You cannot provide native C ++ types or code directly to the .NET framework.

However, there are three ways to interact with "native" C & C ++ code from .NET (in C #, VB.Net, or whatever).

  1. COM
  2. P / Invoke
  3. CLI / C ++

COM is probably the easiest to use from the .NET side. Just add the COM object to your .NET project as a reference and start interacting with the interfaces and classes. For more information on interacting with COM in .NET, read a book like this:

.NET and COM: The Complete Interoperability Guide

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

This, of course, requires that you expose your game engine objects as COM objects. It's not trivial.

The next easiest to use is P / Invoke. If your game code is packaged in a Windows standard DLL with a C calling convention, you can access the functions in that DLL using P / Invoke. For instance:

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);
    }
}

      

You can do a lot with P / Invoke. Even your C / C ++ code will call back to C # with delegates and what not.



In the past, I have created game engine tools that used P / Invoke to call functions provided in a DLL. You just have to be careful about managing native resources. This is where the IDisposable interface and class finalizers become your friends. For instance:

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);
}

      

There is also a downside to using P / Invoke. First, it can add significant overhead to native calls (although there are ways to speed this up). It also requires the C API in gameengine.dll. If your engine is C ++ classes, you must provide a C API for C ++ classes. This can add a lot of work (or require a code generator).

I'm not going to go into all the dirty details of working with Marshalling Managed Objects / Data in and out of native code. Just know that it can be done and that MSDN is your friend here.

The third and probably best way to provide native C ++ code for .NET is through mixed-mode CLI / C ++ assemblies. CLI / C ++ makes it fairly easy to mix native and managed code in the same assembly.

CLI / C ++ has a fun syntax, but if you are a C ++ programmer it is not difficult to adapt. An example would be something like this:

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();
}

      

My recommendation (after doing exactly what you are trying to do) is that for something more than moderately complex, the best solution is to try and provide a CLI / C ++ API for your game engine. I learned everything I needed to know about CLI / C ++ from MSDN, but I heard this book is good if you like meaty volumes.

Expert Visual C ++ / CLI: .NET for Visual C ++ Programmers

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

+4


a source


This article describes the process.

Runtime Type Identification (RTTI) allows you to determine the type of an object at runtime. C # contains three keywords that support runtime type identification: is, as, and typeof.

You use is

to determine if the object you want is needed:

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

      



You are using as

to convert from one object to another. If the transform does not exist, it is returned null

.

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

      

You are using typeof

to get type information.

To get the type of an expression at run time, you can use the .NET Framework's GetType method .

+1


a source







All Articles