
C++/CLI and C#: Writing Managed Wrappers for Native Code

C++/CLI and C#: Writing Managed Wrappers for Native Code
The following article is going to go more in-depth into what is required to write a managed wrapper for a native library or application. It requires making use of an intermediary language called C++/CLI, which syntactically could be simply described as a hybrid between C++ and C# and requires using the /clr or /clr:pure compiler argument when compiling a native library using MSVC.
Syntax
The following section describes the syntax for some core types in C++/CLI.
The Rules
The following section outlines what the rules are when developing libraries that use a combination of C++/CLI.
- Natively declared and defined classes that use "pure" C++ syntax cannot be consumed or referenced directly from C# code.
- References to unmanaged C++ pointers within C++/CLI (managed) types must be declared as private an inaccessible to the consumer in C#.
- "Pure" C++ types that are defined must only hold references to GC roots (i.e. managed heap resources) as void pointers. C++ types must then down-cast the void pointers to the required type, within a function definition.
- Finalizers and destructors play slightly different roles in C++/CLI.
The following is an example C++/CLI class as written in C++ using the /clr compiler option.
#include <msclr.h>
namespace TestNamespace
{
public ref class TestClass
{
public:
TestClass() : _unmanagedPointer(0)
{
}
!TestClass()
{
// This is invoked by the garbage collector
}
~TestClass()
{
// This is invoked with .Dispose()
}
private:
void* _unmanagedPointer;
}
}
When compiled, it can be consumed in C# or any other .NET language as the following.
using TestNamespace;
namespace TestProgram
{
internal class Program
{
private static void Main(string[] args)
{
TestClass testClass = new TestClass();
}
}
}
The Destructor, Finalizer, and Disposable
Writing managed C++ types (C++/CLI) is made more confusing when examining semantic differences for resource mangement. The "destructor" (denoted with ~ character) in C++/CLI is the IDisposable implementation for Dispose. This means that if you are to invoke Dispose on a C++/CLI, it will invoke what is otherwise considered as the destructor in a native C++.
The Finalizer on the other hand is denoted using the ! character, and specifies what gets invoked by the garbage collector when it's time to reclaim resources that are held by the type. It's important to note that while C++/CLI types can be used from both C# and C++, but will ultimately have its memory allocated and managed by the CLR (Common-Language Runtime).
You can find more documentation about this semantic difference in the MSDN documentation.
This is a lot to keep in mind, so the following sections should put more into perspective. For the rest of this blog post I am going to be referencing an existing public code project of mine, ArcaneManagedFbx.
The purpose of this particular code project is to wrap the functionality of the unmanaged (i.e. written in C++) Autodesk FBX SDK into an easily consumable .NET wrapper. My motivations behind creating this project was so that I could conveniently import FBX assets into MonoGame's content processing pipeline on Windows. The FBX file format is copyrighted by Autodesk, meaning that there is no open-sourced file format specification.
Consuming from C#
The following section outlines what is required for consuming a library that is written in C++/CLI.
Consuming from Native C++
It's still possible to write both static and dynamic libraries that are considered to be "native C++" that consume and use C++/CLI types.
Resources
Find below a few interesting links that might help you.
Comments
Comments
I'd still prefer thhe option t᧐ purchase only oncе tо rid mʏself of ads.
The game itself іs very enjoyable, аnd I am enjoying it.
It's good tһat they offered thе capacity tօ play for аn enormous аmount at an affordable cost.
Τhere iѕ aⅼwayѕ room tо improve.Ꮶeep up the ցood ᴡork!