C# – How to create a CLR wrapper of C++ for using in C#?

It has been almost 10 years since last time when I worked with C++. I don’t remember much about C++ syntax and can’t even write a small app with C++ anymore. Since Visual Studio introduces C# and CLR and a lot of changes in C++ development environment. I just ‘quit’ out of this programming language. Moreover in next years, I will focus more in web development, not only for private but also for occupational activities. That mean no chance to come back with C++. I’m afraid that many important things of C++ (that I want to keep) will go with the wind after years. When I need them again, it’ll take me days to bring them back. Creating a CLR wrapper is for me such important thing. So in this small post, I just would like to write down the steps to make a simple CLR wrapper for a C++. This is only a simple CLR wrapper, nothing special, but it always helps me a lot when I try to use C++ library in my C# program.

1. Prerequisites

A little knowledge of C++, a Visual Studio and that’s all.

2. Projects

In this section, we will create a C++ app providing some basic math functions, a CLR wrapper will export and make these functions available to a C# project so that they can be consumed as ‘normal’ ones.

2.1 C++ library

1. In Visual Studio create a new project of Blank solution

Blank Solution

2. Right click on solution in Solution Explorer and add a new project. Browse to template of Visual C++ and select Win32 Console Application. Give A Cpp App as name of project

Win32 Console Application

3. Be sure that you’re creating an Empty project

Empty project

4. In Solution Explorer, right click on A Cpp App project and add new C++ Class CppMath

C++ Class CppMath

5. Under Header Files and Source Files, you’ll see 2 new CppMath.h and CppMath.cpp files. Add following source code to them

CppMath.h

#pragma once
#include <stdexcept>

class CppMath
{
public:
	double Add(double arg1,double arg2);
	double Subtract(double arg1, double arg2);
	double Multiply(double arg1,double arg2);
	double Divide (double arg1,double arg2);
};

CppMath.cpp

#pragma once
#include "CppMath.h"

double CppMath::Add(double arg1,double arg2)
{
	return arg1+arg2;
}

double CppMath::Subtract(double arg1,double arg2)
{
	return arg1-arg2;
}

double CppMath::Multiply(double arg1,double arg2)
{
	return arg1*arg2;
}

double CppMath::Divide(double arg1,double arg2)
{
	if (arg2 == 0)
		throw std::invalid_argument("arg2 can't be zero");
	return arg1/arg2;
}

#pragma once : is a non-standard but widely supported preprocessor directive designed to cause the current source file to be included only once in a single compilation
stdexcept (from cplusplus) : Exception classes.This header defines a set of standard exceptions that both the library and programs can use to report common errors. They are divided in two sets:
Logic errors
logic_error : Logic error exception (class )
domain_error : Domain error exception (class )
invalid_argument : Invalid argument exception (class )
length_error : Length error exception (class )
out_of_range : Out-of-range exception (class )

Runtime errors
runtime_error : Runtime error exception (class )
range_error : Range error exception (class )
overflow_error : Overflow error exception (class )
underflow_error : Underflow error exception (class )

– The C++ will “export” 4 public math functions for using.

6. Add a main.cpp to Source Files and test the code if it works

#include <iostream>
#include "CppMath.h"

int main()
{
	CppMath *cppMath = new CppMath();
	double result = cppMath->Add(1.4,2.7);
	std::cout<<"Result is " <<result<<"\n";

	try
	{
	result = cppMath->Divide(3.8,0);
	std::cout<<"Result is " <<result<<"\n";
	}
	catch (const std::invalid_argument& e)
	{
		std::cerr<<"Invalid argument : " << e.what() << '\n';
	}

	free(cppMath);
	getchar();
	return 0;
}

iostream : Standard Input / Output Streams Library. Header that defines the standard input/output stream objects

If everything is fine, you can compile the project and the test passes.

2.2 CLR Wrapper

1. Right click on Solution and add new project of Class Library

Class Library

2. Add following code to CLRWrapper.h and CLRWrapper.cpp

CLRWrapper.h

// CLR Wrapper.h

#pragma once

#include "CppMath.h"

using namespace System;

namespace CLRWrapper {
	public ref class CppMathWrapper
	{
	public:
		//ctor
		CppMathWrapper();
		//Methods
		double Add(double arg1,double arg2);
	double Subtract(double arg1, double arg2);
	double Multiply(double arg1,double arg2);
	double Divide (double arg1,double arg2);
	private:
		CppMath *cppMath;
	};
}

CLRWrapper.cpp

// This is the main DLL file.

#include "stdafx.h"

#include "CLRWrapper.h"
#include "CppMath.cpp"

CLRWrapper::CppMathWrapper::CppMathWrapper()
{
	cppMath = new CppMath();
}

double CLRWrapper::CppMathWrapper::Add(double arg1,double arg2)
{
	return cppMath->Add(arg1,arg2);
}

double CLRWrapper::CppMathWrapper::Subtract(double arg1,double arg2)
{
	return cppMath->Subtract(arg1,arg2);
}

double CLRWrapper::CppMathWrapper::Multiply(double arg1,double arg2)
{
	return cppMath->Multiply(arg1,arg2);
}

double CLRWrapper::CppMathWrapper::Divide(double arg1,double arg2)
{
	return cppMath->Divide(arg1,arg2);
}

stdafx.h : Precompiled Header Files. An include file for standard system include files and for project-specific include files that are used frequently but are changed infrequently.
– To make a relative #include to CppMath.h and CppMath.cpp, right click on CLR Wrapper project –> Properties –> Configuration Properties –> C/C++ –> Additional Include Directories. Add path to A Cpp App project. It will make CppMath.h and CppMath.cpp available for including.

Additional Include Directories

3. The CLR Wrapper initializes internally an instance of CppMath and create a proxy function for each of CppMath functions. Of course, you can limit or extend the exported functions here. The wrapper works like a proxy and you can control which interfaces are allowed to be public.

4. Compile the project to check if everything is fine.

2.3 C# project

1. Right click on Solution and add new Visual C# Console Application

C# Console Application

2. Add new reference to CLR Wrapper project

Reference to CLR wrapper

3. Now we can use C++ function in our C# program.

private static void Main(string[] args)
{
	CppMathWrapper wrapper = new CppMathWrapper();
	Console.WriteLine(wrapper.Add(1.4, 2.7));
	Console.ReadLine();
}

3. Conclusions

CLR wrapper of C++ is very helpful when we already have an existing working code and want to use it in managed application. We can of course limit or extend the public functions in our CLR wrapper. The only disadvantage of CLR wrapper is defining proxy functions for all public functions. However writing proxy functions is pretty simple, it’s a little time consuming but not extremely complicated.

Source code: https://bitbucket.org/hintdesk/dotnet-how-to-create-a-clr-wrapper-of-c-for-using-in-c

Leave a Reply

Your email address will not be published. Required fields are marked *