What are C++ Interops?
C++ Interop enables calling C++ code from C# code by utilizing various techniques and libraries provided by the .NET Framework, including Platform Invocation Services (P/Invoke), COM Interop, and C++/CLI.
What are the benefits of C++ Interops in C#?
There are several benefits of using C++ Interops functionality in C# code, they are described below.
By reusing existing C++ code that is already available, we can avoid the need to develop the same functionality from scratch for C#, resulting in significant time and effort savings.
C++ Interop in C# allows us to leverage the low-level hardware and memory manipulation capabilities of C++, enabling us to access them directly from our C# application.
When performance is crucial and there is a need to optimize code, C++ Interop in C# can be utilized to leverage the power of C++ and improve the application's performance.
C++ Interop in C# allows for seamless integration of third-party C++ libraries into your C# application. Additionally, it enables access to system-specific libraries, such as User32.dll and system32.dll.
How to use C++ Interop functionality in C# and how we can create Interop DLL in C++?
Create a C++ dll project and add the following code to the header file, I have added it as CustomClass.h.
#pragma once
#include <iostream>
#ifdef CPPDEMOLIB_EXPORTS
#define DemoLib __declspec(dllexport)
#else
#define DemoLib __declspec(dllimport)
#endif // CPPDEMOLIB_EXPORTS
using namespace std;
DemoLib class CustomClassLib
{
public:
CustomClassLib();
int AddNumbers(int num1, int num2);
void DisplayMessage(char* message, char* buffer);
~CustomClassLib();
};
extern "C" DemoLib CustomClassLib * Initialize() { return new CustomClassLib(); }
extern "C" DemoLib int AddNumbers(CustomClassLib classObj, int num1, int num2) { return classObj.AddNumbers(num1, num2); }
extern "C" DemoLib void DisplayMessage(CustomClassLib classObj, char* message, char* buffer) { classObj.DisplayMessage(message, buffer); }
extern "C" DemoLib void DeleteObj(CustomClassLib * classObj) { delete classObj; }
This code defines a C++ class called CustomClassLib that is intended to be used in a C# project via a DLL. The code includes the standard input/output stream library, defines a header guard, and uses a preprocessor directive to check whether the DLL is being exported or imported.
The CustomClassLib class has three member functions: a constructor, an addition function, and a message display function, as well as a destructor. The DemoLib attribute is used to indicate whether the class is being compiled as a DLL or an executable.
External functions are defined using the "extern C" keyword to ensure they are exported with C-style naming, which makes it easier for the C# wrapper to access them. Overall, this code is designed to be compiled into a DLL that can be used in a C# project via a wrapper.
The add following code to the Source file, i.e. CustomClass.cpp.
#include "CustomClass.h"
#include <iostream>
#include <string>
using namespace std;
CustomClassLib::CustomClassLib() {
cout << "Intialize Library" << endl;
}
int CustomClassLib::AddNumbers(int num1, int num2) {
try
{
int _sum = num1 + num2;
return _sum;
}
catch (const std::exception& e)
{
cout << "Error:" << e.what() << endl;
return -1;
}
}
void CustomClassLib::DisplayMessage(char* message, char* buffer) {
try
{
char cArray[255];
sprintf_s(cArray, "Hello, %s", message);
strcpy_s(buffer, sizeof(cArray), cArray);
}
catch (const std::exception& e)
{
cout << "Error:" << e.what() << endl;
}
}
CustomClassLib::~CustomClassLib() {
}
This code defines the member functions of a C++ class called CustomClassLib, which can be used in a C# project via a DLL.
The constructor function CustomClassLib() simply outputs a message to the console when the class is initialized.
The AddNumbers() function takes two integer arguments, adds them together, and returns their sum. It also includes error handling in case an exception is thrown.
The DisplayMessage() function takes a character array argument and writes a message to it, which is then copied to another character array buffer. Again, error handling is included.
The destructor function ~CustomClassLib() is empty.
Overall, this code provides basic functionality for the CustomClassLib class, allowing it to be used in a C# project via a DLL.
Now we need to use these Interop functions in a C# program for it, we can add the following code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace InteropDemo
{
internal class Program
{
static void Main(string[] args)
{
IntPtr _myClassObj = ExternHelpers.Initialize();
int sum = ExternHelpers.AddNumbers(_myClassObj, 100, 56);
Console.WriteLine("From CPP -> AddNumbers :" + sum);
StringBuilder sb=new StringBuilder(255);
ExternHelpers.DisplayMessage(_myClassObj, "Have a wonderful day, keep learning.",sb);
Console.WriteLine("From CPP -> Display Message: " + sb.ToString());
ExternHelpers.DeleteObj(_myClassObj);
Console.Read();
}
}
public static class ExternHelpers
{
const string dllName = "CppDemoLib.dll";
[DllImport(dllName)]
public static extern IntPtr Initialize();
[DllImport(dllName)]
public static extern int AddNumbers(IntPtr myClassObj, int num1, int num2);
[DllImport(dllName)]
public static extern void DisplayMessage(IntPtr myClassObj, string message,StringBuilder responseMessage);
[DllImport(dllName)]
public static extern void DeleteObj(IntPtr myClassObj);
}
}
This is a C# code that demonstrates how to use a C++ DLL in a C# project using interop. The C# program defines a class called "Program" with a Main method that calls several functions from a C++ DLL called "CppDemoLib.dll".
The program first initializes the DLL by calling the "Initialize" method from the DLL through the "ExternHelpers" class. Then it calls the "AddNumbers" method, which takes two integers as arguments and returns their sum. It also calls the "DisplayMessage" method, which takes a string message and a StringBuilder as arguments and writes the message to the StringBuilder.
Finally, it calls the "DeleteObj" method to clean up the instance of the C++ class. The interop is facilitated by the [DllImport] attribute which allows the C# program to access the functions in the C++ DLL.
Conclusion
Integrating C++ code in a C# project can seem daunting at first, but with the right tools and knowledge, it can be a powerful way to enhance your application's performance and functionality. By following the steps outlined in this blog post, you can get started with integrating C++ code in your C# project using DLLs.