Jump to content
  • Advertisement
Sign in to follow this  
Chris_F

C# interop with C++

This topic is 2565 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

So I'd like to interface my own C++ code with C#. There are a many ways of doing this, but some are more appealing than others. C++/CLI wrapper is out of the question. I don't use Microsoft's C++ compiler, and I don't plan to. I'd also like to avoid having to create a set of wrappers in C.

Lets say I use the following interface for my C++ code:

[source lang=cpp]
#include <string>

class TestObject
{
public:
TestObject(const std::string _str)
: str(_str)
{}
virtual const char* getString()
{
return str.c_str();
}
virtual void destroy()
{
delete this;
}
private:
~TestObject() {}
std::string str;
};

extern "C"
{
__declspec(dllexport) __cdecl TestObject* CreateTestObject(const char* str)
{
return new TestObject(str);
}
}
[/source]

[source lang=cpp]
public struct __TestObject
{
public struct vtable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate string getStringDelegate(IntPtr p);

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void destroyDelegate(IntPtr p);

public getStringDelegate getString;
public destroyDelegate destroy;
}

[DllImport("TestObject.dll", EntryPoint = "CreateTestObject", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern IntPtr Create(string filename);

public IntPtr _vtable;
}

public class TestObject : IDisposable
{
private IntPtr pTestObject;
private __TestObject.vtable _vtable;

public TestObject(string str)
{
pTestObject = __TestObject.Create(str);
var obj = (__TestObject)Marshal.PtrToStructure(pTestObject, typeof(__TestObject));
_vtable = (__TestObject.vtable)Marshal.PtrToStructure(obj._vtable, typeof(__TestObject.vtable));
}

public string GetString()
{
return _vtable.getString(pTestObject);
}

public void Dispose()
{
_vtable.destroy(pTestObject);
}
}
[/source]

So my question is, how good of a solution is this? Does anyone else use something similar?

Share this post


Link to post
Share on other sites
Advertisement
AFAIK, to use these kinds of tricks, you've got to tell C# that your struct is using a C++-like memory layout by using [font="Courier New"][StructLayout(LayoutKind.Sequential, Pack = 4)][/font].
There's a blog-post on a similar technique here: http://blogs.msdn.co...class-in-c.aspx

Unless I've mis-read what you're doing, this is still compiler-dependent as the compiler is free to implement the v-table however it wants to (I've used one C++ compiler that put it at the end of the object). In your C++ code, you should probably also manually specify the calling convention to be sure that it matches the manually specified convention on the C# side.

To avoid this fragility, I'd personally use C++/CLI, but failing that, a plain C-wrapper of the CPP code, followed by a C#-wrapper of the C code.

Share this post


Link to post
Share on other sites
I thought __declspec(dllexport) was Microsoft specific? Or perhaps Intel?

Anyway, I've never seen anyone do anything like that, so I'm a bit skeptical. It looks to me like you are relying on undocumented/implementation-defined behaviour which is just begging for trouble, especially if you are aiming for cross platform support.

If I wanted to interface with C++ code, I would use C++/CLI since I'm only on Windows anyway. If not C++/CLI, I would look into how .NET + COM works. I think I read somewhere that a C++ interface (class with only abstract methods and no variables) can map to a .NET interface if all members are declared in the same order. I have not verified this, I don't know if it's portable and I'm not sure if there are other requirements on the C++ and/or C# code. It's also possible that it comes with overhead.

Share this post


Link to post
Share on other sites
The best advice I can give you is to use C++/CLI, or don't bother with C#. C++ is not a fun language to interop with. If your interfaces that you need to call are in any way complex, you (or a coworker, if this is not a personal project) will be in an immense world of pain if you do it any other way.

(edit)


If not C++/CLI, I would look into how .NET + COM works. I think I read somewhere that a C++ interface (class with only abstract methods and no variables) can map to a .NET interface if all members are declared in the same order. I have not verified this, I don't know if it's portable and I'm not sure if there are other requirements on the C++ and/or C# code. It's also possible that it comes with overhead.


Yes, this is another option. I don't know if any non-microsoft compilers support COM, though. It's also kind of a pain to write COM classes compared to C++/CLI.

Share this post


Link to post
Share on other sites

Unless I've mis-read what you're doing, this is still compiler-dependent as the compiler is free to implement the v-table however it wants to


Well, I'm sure if you look hard enough, you could find one that doesn't work. In any case, any modern c++ compiler is likely to work, since in order to support COM they need to adhere to the COM ABI specification, which requires that a vtable pointer be the first thing in an abject and for the order of the vtable function pointers match the order in which the functions were declared. To my knowledge, the only thing the COM ABI doesn't specify is how to handle multiple or virtual inheritance, virtual destructors and possibly overloaded functions as well. As long as you don't use those, this should be widely compatible.

Edit: For instance, GCC used to have an __attribute__((com_interface)) to specify that you wanted a class to be compiled with COM vtables, and if you try to use that these days, GCC will state that it is deprecated and that it uses COM compatible vtables by default.



I thought __declspec(dllexport) was Microsoft specific? Or perhaps Intel?


Yes, __declspec(dllexport) was Microsoft's brain child, but that didn't stop Intel and GCC from following suit.

[quote name='Nypyren']
I don't know if any non-microsoft compilers support COM, though
[/quote]

Of course they do! What good would a compiler for Windows be without COM support?

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!