[.net] Interfacing c# with unmanaged c++
I have a "engine" written in C++ and compiled into a .lib file and I would like to make the editor in C# because after messing around with it for a while I found out how easy it was to make GUI apps with it. Unfortuanatly I can't find anything about interfacing managed code with native code. I hear about it and how it's really hard but I can't find any information on it. I searched with google but I can't find anything about it (I get things like . If anyone could point me to some resources or explain it to me it would be much appreciated.
Interfacing with c++ can get complicated, as it requires you to expose your engine as COM+ interfaces. However if its possible to use your engine with C functions, interfacing is a piece of cake.
Firstly, your engine will need to be built as a dll, then export a set of functions such as:
then in the editor,
Certainly easier than COM+ but it requires you to write a abstraction layer on top of your engine in C.
Firstly, your engine will need to be built as a dll, then export a set of functions such as:
typedef int* EngineHandle;extern "C" _declspec(dllexport) EngineHandle* CreateEngine();extern "C" _declspec(dllexport) void DrawModel(EngineHandle *pEngine, char *data);etc.
then in the editor,
namespace Engine{ class Native { [DllImport("engine.dll", EntryPoint="CreateEngine", CallingConvention=CallingConvention.StdCall)] public static extern IntPtr CreateEngine(); [DllImport("engine.dll", EntryPoint="DrawModel", CallingConvention=CallingConvention.StdCall)] public static extern void DrawModel(IntPtr pEngine, byte[] data); }}
Certainly easier than COM+ but it requires you to write a abstraction layer on top of your engine in C.
Or you can create a managed class around your engine:
Note that the syntax I show here is for .NET 1.0/1.1 (VS.NET 2002/2003), and has been deprecated for CLI/C++ in .NET 2.0 (VS.NET 2005).
namespace Blah{__gc public class Engine{private: NativeEngine* m_engine;public: void Initialize(System::Windows::Form* form) { HWND hwnd = (HWND)form->Handle; m_engine->InitializeDirectX(hwnd); } void Render() { m_engine->Render(); }};}
This page has the managed C++ reference. Then you can use the object in C# as follows (after importing the DLL into your project):Form mainForm;Blah.Engine engine = new Blah.Engine();engine.Initialize(mainForm);engine.Render();
Note that the syntax I show here is for .NET 1.0/1.1 (VS.NET 2002/2003), and has been deprecated for CLI/C++ in .NET 2.0 (VS.NET 2005).
Nice repiles. I learned a lot aswell. I've been wanting to do this project for a few months but in C# and i need to use a DLL written in C++. Im much more compentant with C++ and doing the equilvant work C# would be really hard for me if not impossible right now.
I have a question please for the love of all thats holy someone that knows answer please..
Okay i finally got a mixed DLL working with C# using a proxy a class, thanks Mutex.
Everything is working it seems.
Except i don't know how to pass char*'s to the DLL and return them from the DLL. Numeric params and returns are working.
How would I get this type of code to work right in C#?
Im so close to actually get this program i envisioned off the ground please help!
Amnesty
I have a question please for the love of all thats holy someone that knows answer please..
Okay i finally got a mixed DLL working with C# using a proxy a class, thanks Mutex.
Everything is working it seems.
Except i don't know how to pass char*'s to the DLL and return them from the DLL. Numeric params and returns are working.
How would I get this type of code to work right in C#?
[source language="C#"]Native.ReplayProxy proxy = new Native.ReplayProxy();string b = "hello";string c;proxy.accept_cstr(b);c = proxy.return_cstr();
Im so close to actually get this program i envisioned off the ground please help!
Amnesty
You have to massage strings a bit to cross the .NET boundary. To go from C/C++ strings to .NET, you simply construct a System::String object and pass the string in as a parameter. System::String() can take char* or wchar_t* as input. To go from a .NET string back to a character array you need to use a function to access the underlying buffer, and then copy that to your own buffer.
This page has some info on it. Double-check my .NET->std::string conversion, I'm on incredibly little sleep and it might have bugs.
#include <vcclr.h> // for PtrToStringCharsusing namespace System;// Convert to System.String, which has constructors for both char* and wchar_t*.std::string std_string = "std string";String* net_string = new String(std_string.c_str());Console::WriteLine(net_string);// Convert from System.String.// p is a pointer to the character buffer in netstring, but since netstring// is a garbage-collected object, it may move. __pin prevents the object from// moving in memory.String* netstring = new String(_T("Hello from .NET"));const wchar_t __pin* p = PtrToStringChars(netstring);// Note that p is a wide string, need to convert to char* to allow construction// with std::string.size_t length = wcslen(p);char* rawstring = new char[length+1];wcstombs(rawstring, p, length+1);std_string = string(rawstring);delete [] rawstring;std::cout << std_string << std::endl;
This page has some info on it. Double-check my .NET->std::string conversion, I'm on incredibly little sleep and it might have bugs.
@Mutex, your idea does sound like it would be ok but unfortuanatly I do not have access to a managed C++ compiler.
@Baron_von_PartyHat: I'm not sure I would wan't to do that, but if I can't come up with another way I will do it that way.
Is there another possible way?
@Baron_von_PartyHat: I'm not sure I would wan't to do that, but if I can't come up with another way I will do it that way.
Is there another possible way?
::Mutex, your idea does sound like it would be ok but unfortuanatly I do not
::have access to a managed C++ compiler.
How comes? Isnt't a C++ compiler part of the .NET framework?
Without a maanged C++ compiler you are - sorry - fucked. Interop sis limited and ina lot of situations turns into a pain. Managed C++ is THE solution to make a separate DLL that exposes .NET classes and talks "native" to the underlying engine.
Been there, tried, cured - in my case it was the attempt to use the standard ISDN-interface from C# which resulted in tons of hardly maintainable code. Or to use DIrectShow (low level) - same result. Managed C++ is painless on these API's.
Get a managed C++ compiler.
::have access to a managed C++ compiler.
How comes? Isnt't a C++ compiler part of the .NET framework?
Without a maanged C++ compiler you are - sorry - fucked. Interop sis limited and ina lot of situations turns into a pain. Managed C++ is THE solution to make a separate DLL that exposes .NET classes and talks "native" to the underlying engine.
Been there, tried, cured - in my case it was the attempt to use the standard ISDN-interface from C# which resulted in tons of hardly maintainable code. Or to use DIrectShow (low level) - same result. Managed C++ is painless on these API's.
Get a managed C++ compiler.
Well I am using Visual C# express and that didn't come with Visual C++. Oh well Im off to spend another few hours downloading Visual C++ express....
Does the Visual C++ Toolkit compiler (eg: VC++ 7.1) support the /clr compiler option? If so, you should be able to compile managed code with that.
ONDotNet has a couple of decent intro tutorials to writing managed C++ wrappers (Look for Sam Gentile's articles).
ONDotNet has a couple of decent intro tutorials to writing managed C++ wrappers (Look for Sam Gentile's articles).
It might be easier just to have a common file format for the "editor" and the "engine". That way you don't need to interface the two, you just share the files.
Though I guess if your editor needs to use your engine directly, that approach won't work for you.
Though I guess if your editor needs to use your engine directly, that approach won't work for you.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement