[.net] Interfacing c# with unmanaged c++

Started by
10 comments, last by Amnesty 19 years, 1 month ago
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.
______________________________________________________________________________________With the flesh of a cow.
Advertisement
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:

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:
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#?

[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
"I turned into a driveway I thought was mine and crashed into a tree I don't have."- a real insurance claim
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.

#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?
______________________________________________________________________________________With the flesh of a cow.
::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.
RegardsThomas TomiczekTHONA Consulting Ltd.(Microsoft MVP C#/.NET)
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....
______________________________________________________________________________________With the flesh of a cow.
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).
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.
Anything posted is personal opinion which does not in anyway reflect or represent my employer. Any code and opinion is expressed “as is” and used at your own risk – it does not constitute a legal relationship of any kind.

This topic is closed to new replies.

Advertisement