I am developing game editor in C# that uses c++ lib files. I want RTTI for C++ classes in C#. Is it possible to get RTTI of C++ class in C#? If yes how?
This article describes the process.
Runtime Type Identification(RTTI) allows the type of an object to be determined during program execution. C# includes three keywords that support runtime type identification: is, as and typeof.
You use is
to determine whether an object is of the type you want:
if (myVariable is string)
{
// do stuff
}
You use as
to convert from one object to another. If no conversion exists then null
is returned.
string myString = myVariable as string;
if (myString != null)
{
// do stuff
}
You use typeof
to obtain information about a type.
To obtain the run-time type of an expression, you can use the .NET Framework method GetType.
You can not expose native C++ types or code directly to the .NET platform.
There are however three ways of interacting with "native" C & C++ code from .NET (in C#, VB.Net or whatever).
- COM
- P/Invoke
- 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 detail on interactive with COM in .NET have a read of a book like this:
http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X
This of course requires you to expose your game engine objects as COM objects. This is non-trivial.
The next easiest to use is P/Invoke. If your game code is packaged in a standard windows DLL with a C calling convention you can access functions in that DLL using P/Invoke. For example:
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 have your C/C++ code call back into C# with delegates and what not.
I've built game engine tools in the past that used P/Invoke to call out to functions exposed in a DLL. You just have to be careful about the management of native resources. Here the IDisposable interface and class finalizers become your friends. Eg:
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 a downside to using P/Invoke. First it can add a significant marshalling overhead to native calls (though there are ways of speeding that up). It also requires a C API in the gameengine.dll. If your engine is C++ classes you have to provide a C API to the C++ classes. This can add a whole lot of work (or require a code generator).
I'm not going to go into any more detail on all the messy details of dealing with Marshalling managed objects/data to and from native code. Just know that it can be done and that MSDN is your friend here.
The third and probably best way of exposing native C++ code to .NET is via CLI/C++ mixed mode assemblies. CLI/C++ lets you mix native and managed code together in a single assembly fairly seamlessly.
CLI/C++ has a funny syntax but if you're a C++ programmer it is not hard to adapt. An example might 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 (having done exactly what you're trying to do) is that for anything more than moderately complex, the best solution is to try and provide a CLI/C++ API to your game engine. I learnt everything I needed to know about CLI/C++ off MSDN but I hear this book is good if you like meaty tomes.
http://www.amazon.com/Expert-Visual-CLI-Programmers-Experts/dp/1590597567