C++ via C#
Egor Bogatov
@EgorBo
Calling C++ from C#. For what?
• Lovely IDE + R#
• Syntactic sugar
• nuget
Calling C++ from C#. How?
• C++/CLI
• COM
• [DllImport], [MethodImpl]
• IPC, Sockets,…
Calling C++ from C#. How?
• C++/CLI
• COM
• [DllImport], [MethodImpl]
• IPC, Sockets,…
UrhoSharp
• ~ 200 classes
• ~ 5000 methods
• Same FPS
• +10% memory
• C# for:
Windows
Mac OS
Android
iOS
tvOS
Urho3D API
class Node : public Animatable
{
public:
Node(Context* context);
void SetName(const String& name);
const String& GetName();
void SetPosition(const Vector3& position);
const Vector3& GetPosition();
void AddChild(Node* node, unsigned index = M_MAX_UNSIGNED);
void RemoveChild(Node* node);
};
public class Node : Animatable
{
public Node(Context context) { }
public string Name { get; set; }
public Vector3 Position { get; set; }
void AddChild(Node node, uint index = uint.MaxValue) { }
void RemoveChild(Node node) { }
}
Node.cpp
C++
C#
Urho3D API
class Node : public Animatable
{
public:
Node(Context* context);
void SetName(const String& name);
};
glue.cpp
Urho3D API
Node.cpp
C#
Node node = new Node(context);
node.SetName("foo");
Node* node = new Node(context_);
node->SetName("foo");
Urho3D APIvoid SetName(const String& name);
extern "C"
DllExport void Node_SetName (Node *target, const char * name){
target->SetName (Urho3D::String(name));
}
[DllImport ("mono-urho", …)]
static extern void Node_SetName (IntPtr handle, string name);
public void SetName (string name) { Node_SetName (handle, name);
Node.cppNode.h
binding.cpp
Node.cs
original API
generated
generated
Urho3D API
class Node : public Animatable
{
public:
Node(Context* context);
void SetName(const String& name);
};
DllExport void* Node_Node (Context * context) {
return new Node(context);
}
DllExport void Node_SetName (Node *target, const char * name) {
target->SetName (Urho3D::String(name));
}
public partial class Node : Animatable
{
private IntPtr handle;
[DllImport ("mono-urho")]
static extern IntPtr Node_Node (IntPtr context);
public Node (Context context) { handle = Node_Node (context.Handle); }
[DllImport ("mono-urho")]
static extern void Node_SetName (IntPtr handle, string name);
public void SetName (string name) { Node_SetName (handle, name);
Node.cppNode.h
binding.cpp
Node.cs
original API
generated
generated
Binding flow
Urho3D sources
(*.cpp, *.h)
Urho.pch
Generator (Binder)
binding.cpp *.cs
UrhoSharp.dll
Win: mono-urho.dll
Droid: libmono-urho.so
OSX: libmono-urho.dylib
iOS: urho.framework
nuget package
all-urho.cpp via clang
roslyn
• clang
• gcc
• msvc
clang.dll
Nrefactory.dll
PCL, Profile7
Object lifecycle
RefCounted:
• AddRef
• ReleaseRef
• RefsCount
• ~dctor
Node node = new Node(context)
1) Allocate a native object (Node* node = new Node)
scene.AddNode(node)
2) AddRef is called, callback to managed code
3) Managed code receives the callback, adds hard reference to node
scene.RemoveAll();
5) Managed code receives callback from native ~dctor,
removes reference. GC is now able to collect empty wrapper.
6) GC collects managed wrapper
Egor Bogatov
@EgorBo
github:
• UrhoSharp
• CppSharp

C++ via C#

  • 1.
    C++ via C# EgorBogatov @EgorBo
  • 2.
    Calling C++ fromC#. For what? • Lovely IDE + R# • Syntactic sugar • nuget
  • 3.
    Calling C++ fromC#. How? • C++/CLI • COM • [DllImport], [MethodImpl] • IPC, Sockets,…
  • 4.
    Calling C++ fromC#. How? • C++/CLI • COM • [DllImport], [MethodImpl] • IPC, Sockets,…
  • 5.
    UrhoSharp • ~ 200classes • ~ 5000 methods • Same FPS • +10% memory • C# for: Windows Mac OS Android iOS tvOS
  • 6.
    Urho3D API class Node: public Animatable { public: Node(Context* context); void SetName(const String& name); const String& GetName(); void SetPosition(const Vector3& position); const Vector3& GetPosition(); void AddChild(Node* node, unsigned index = M_MAX_UNSIGNED); void RemoveChild(Node* node); }; public class Node : Animatable { public Node(Context context) { } public string Name { get; set; } public Vector3 Position { get; set; } void AddChild(Node node, uint index = uint.MaxValue) { } void RemoveChild(Node node) { } } Node.cpp C++ C#
  • 7.
    Urho3D API class Node: public Animatable { public: Node(Context* context); void SetName(const String& name); }; glue.cpp
  • 8.
    Urho3D API Node.cpp C# Node node= new Node(context); node.SetName("foo"); Node* node = new Node(context_); node->SetName("foo");
  • 9.
    Urho3D APIvoid SetName(constString& name); extern "C" DllExport void Node_SetName (Node *target, const char * name){ target->SetName (Urho3D::String(name)); } [DllImport ("mono-urho", …)] static extern void Node_SetName (IntPtr handle, string name); public void SetName (string name) { Node_SetName (handle, name); Node.cppNode.h binding.cpp Node.cs original API generated generated
  • 10.
    Urho3D API class Node: public Animatable { public: Node(Context* context); void SetName(const String& name); }; DllExport void* Node_Node (Context * context) { return new Node(context); } DllExport void Node_SetName (Node *target, const char * name) { target->SetName (Urho3D::String(name)); } public partial class Node : Animatable { private IntPtr handle; [DllImport ("mono-urho")] static extern IntPtr Node_Node (IntPtr context); public Node (Context context) { handle = Node_Node (context.Handle); } [DllImport ("mono-urho")] static extern void Node_SetName (IntPtr handle, string name); public void SetName (string name) { Node_SetName (handle, name); Node.cppNode.h binding.cpp Node.cs original API generated generated
  • 11.
    Binding flow Urho3D sources (*.cpp,*.h) Urho.pch Generator (Binder) binding.cpp *.cs UrhoSharp.dll Win: mono-urho.dll Droid: libmono-urho.so OSX: libmono-urho.dylib iOS: urho.framework nuget package all-urho.cpp via clang roslyn • clang • gcc • msvc clang.dll Nrefactory.dll PCL, Profile7
  • 12.
    Object lifecycle RefCounted: • AddRef •ReleaseRef • RefsCount • ~dctor Node node = new Node(context) 1) Allocate a native object (Node* node = new Node) scene.AddNode(node) 2) AddRef is called, callback to managed code 3) Managed code receives the callback, adds hard reference to node scene.RemoveAll(); 5) Managed code receives callback from native ~dctor, removes reference. GC is now able to collect empty wrapper. 6) GC collects managed wrapper
  • 13.

Editor's Notes

  • #12 Add 2/3 circles aligned in a row on a separate slide.