Jump to content
  • Advertisement
Sign in to follow this  
Ainokea

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

This topic is 4824 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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 PtrToStringChars
using 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.

Share this post


Link to post
Share on other sites
@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?

Share this post


Link to post
Share on other sites
::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.

Share this post


Link to post
Share on other sites
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....

Share this post


Link to post
Share on other sites
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).

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!