Skip to content
/ monopp Public

Mono wrapper for c++14 for embedding C# into C++

License

Notifications You must be signed in to change notification settings

volcoma/monopp

Repository files navigation

windows linux macos

A C++14 wrapper for embeddig C# into C++ using Mono. Clean and easy API.

Only dependency is c++ standard library and Mono.

Make sure you download the latest Mono stable version.

Not feature complete but useable.


Consists of 3 small projects.

  • monopp - C++14 wrapper for mono runtime.

  • monort - utility providing ease of binding custom pod/non-pod types for interop.

  • tests - tests and examples using the library.


C++

	if(!mono::init("mono", true))
	{
		return 1;
	}
	/// Create an app domain. When destructed it will
	/// unload all loaded assemblies
	mono::mono_domain my_domain("my_domain");

	/// Sets the current domain
	mono::mono_domain::set_current_domain(my_domain);

	/// Get or load an assembly
	auto assembly = my_domain.get_assembly("tests_managed.dll");

	/// Get access to a c# type
	auto type = assembly.get_type("Tests", "MonoppTest");

	/// Prints out Tests
	std::cout << type.get_namespace() << std::endl;

	/// Prints out MonoppTest
	std::cout << type.get_name() << std::endl;

	/// Prints out Tests.MonoppTest
	std::cout << type.get_fullname() << std::endl;

	/// Checks and gets the base type of Tests.MonoppTest
	if(type.has_base_type())
	{
		auto base_type = type.get_base_type();
		std::cout << base_type.get_fullname() << std::endl;
	}

	/// Create an instance of it. Default constructed.
	auto obj = type.new_instance();

	/// There are several ways of getting access to methods
	/// Way 1, name + arg count
	auto method1 = type.get_method("Method1", 0);

	/// You can invoke it by creating a thunk and calling it passing
	/// the object it belongs to as the first parameter. Not passing
	/// an object as the first parameter will treat it as a static method
	auto thunk1 = mono::make_method_invoker<void()>(method1);
	thunk1(obj);

	/// Way 2, name + args
	auto method2 = type.get_method("Method2(string)");
	auto thunk2 = mono::make_method_invoker<void(std::string)>(method2);
	thunk2(obj, "str_param");

	/// Way 3, use the template method
	auto method3 = mono::make_method_invoker<std::string(std::string, int)>(type, "Method5");
	auto result3 = method3(obj, "test", 5);

	/// You can also get and invoke static methods without passing
	/// an object as the first parameter
	auto method4 = mono::make_method_invoker<int(int)>(type, "Function1");
	auto result4 = method4(55);
	std::cout << result4 << std::endl;
	/// You can query various information about a method
	method1.get_name();
	method1.get_fullname();
	method1.get_full_declname();
	method1.get_visibility();
	method1.is_static();
	method1.get_param_types();
	method1.get_return_type();
	/// etc.

	/// You can catch exceptions like so
	try
	{
		mono::make_method_invoker<int(int, float)>(type, "NonExistingFunction");
	}
	catch(const mono::mono_exception& e)
	{
		std::cout << e.what() << std::endl;
	}

	/// You can access type fields by name
	auto field = type.get_field("someField");

	/// In order to get or set values to a field you need
	/// to create an invoker.
	auto mutable_field = mono::make_field_invoker<int>(field);

	/// You can get their values. Not passing an
	/// object as the parameter would treat
	/// it as being static.

	auto field_value = mutable_field.get_value(obj);
	std::cout << field_value << std::endl;

	/// You can set their values. Not passing an
	/// object as the parameter would treat
	/// it as being static.
	int field_arg = 55;
	mutable_field.set_value(obj, field_arg);

	/// You can query various information for a field.
	field.get_name();
	field.get_fullname();
	field.get_full_declname();
	field.get_type();
	field.get_visibility();
	field.is_static();
	/// etc..

	auto prop = type.get_property("someProperty");

	/// In order to get or set values to a field you need
	/// to create an invoker.
	auto mutable_prop = mono::make_property_invoker<int>(prop);

	/// You can get their values. Not passing an
	/// object as the parameter would treat
	/// it as being static.
	auto prop_value = mutable_prop.get_value(obj);
	std::cout << prop_value << std::endl;

	/// You can set their values. Not passing an
	/// object as the parameter would treat
	/// it as being static.
	int prop_arg = 55;
	mutable_prop.set_value(obj, prop_arg);

	/// You can get access to the get and set
	/// methods of a property
	auto getter = prop.get_get_method();
	auto setter = prop.get_set_method();
	/// You can treat these methods as you would any other method
	auto getter_thunk = mono::make_method_invoker<int()>(getter);
	prop_value = getter_thunk(obj);
	std::cout << prop_value << std::endl;

	auto setter_thunk = mono::make_method_invoker<void(int)>(setter);
	setter_thunk(obj, 12);

	/// You can query various information for a field.
	prop.get_name();
	prop.get_fullname();
	prop.get_full_declname();
	prop.get_type();
	prop.get_visibility();
	prop.is_static();
	/// etc..

	/// Get all the fields of the type
	auto fields = type.get_fields();

	for(const auto& f : fields)
	{
		std::cout << f.get_full_declname() << std::endl;
	}

	/// Get all the properties of the type
	auto props = type.get_properties();

	for(const auto& p : props)
	{
		std::cout << p.get_full_declname() << std::endl;
	}

	/// Get All the methods of the type
	auto methods = type.get_methods();

	for(const auto& method : methods)
	{
		std::cout << method.get_full_declname() << std::endl;
	}
	mono::shutdown();

C#

using System;
using System.Runtime.CompilerServices;

namespace Tests
{
class MonoppTest
{

	public int someField = 12;

	public int someProperty
	{
		get
		{
			return someField;
		}
		set
		{
			Console.WriteLine("FROM C# : Setting property value to {0}", value);
			someField = value;
		}
	}

	public static int someFieldStatic = 12;

	public static int somePropertyStatic
	{
		get
		{
			return someFieldStatic;
		}
		set
		{
			Console.WriteLine("FROM C# : Setting static property value to {0}", value);
			someFieldStatic = value;
		}
	}
	
	static MonoppTest()
	{
		Console.WriteLine("FROM C# : STATIC CONSTRUCTOR.");
	}
	public MonoppTest()
	{
		Console.WriteLine("FROM C# : MonoppTest created.");
	}
	~MonoppTest()
	{
		Console.WriteLine("FROM C# : MonoppTest destroyed.");
	}
	
	void Method1()
	{
		Console.WriteLine("FROM C# : Hello Mono World from instance.");
	}
	
	void Method2(string s)
	{
		Console.WriteLine("FROM C# : WithParam string: " + s);
	}
	void Method3(int s)
	{
		Console.WriteLine("FROM C# : WithParam int: " + s);
	}
	void Method4(int s, int s1)
	{
		Console.WriteLine("FROM C# : WithParam int, int: {0}, {1}", s, s1);
	}
	
	public string Method5(string s, int b)
	{
		Console.WriteLine("FROM C# : WithParam: {0}, {1}", s, b);
		return "Return Value: " + s;
	}

	public static int Function1(int a)
	{
		Console.WriteLine("FROM C# : Int value: " + a);
		return a + 1337;
	}

	public static void Function2(float a, int b, float c)
	{
		Console.WriteLine("FROM C# : VoidMethod: {0}, {1}, {2}", a, b, c);
	}

	public static void Function3(string a)
	{
		Console.WriteLine("FROM C# : String value: {0}", a);
	}

	public static string Function4(string str)
	{
		return "The string value was: " + str;
	}
	
	public static void Function5()
	{
		throw new Exception("Hello!");
	}
}
}

About

Mono wrapper for c++14 for embedding C# into C++

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages