.NET PInvoke Interop SDK for C++ DLL

A C# Wrapper Generator for Wrapping Native C++ DLL Automatically

        - A tool capable of creating C# wrapper class for native C++ class instantly

 

xInterop NGen++ 2.0 has been released

The C# / .NET PInvoke Interop SDK includes a C# Wrapper Generator for C++ DLLs and a C# library for wrapping C++ standard classes.

For years, developers have been struggling with being unable to calling into C++ DLL from .NET easily. To access native C++ classes exported in a C++ DLL from .NET world, there are a few existing technologies, all of them require developers’ extra effort to write either script or C++ code to create a managed .NET wrapper DLL to access the original C++ DLL, and there will be more work when you consider the maintenance, none of them are automatic.

Wrapping C++ classes from C#/.NET enables developers to access their existing C++ code base in the C#/.NET world without manually changing anything or writing anything extra. The only things this SDK tool requires is the DLL itself and all the header files for that DLL, just like being referenced from a C++ project, it does not even require the corresponding lib file for the native C++ DLL as normally being required by a C++ compiler when using the DLL from a C++ project. Instead of converting all your C++ code to C# .NET code, using C++ DLL or class from your C# code is the ideal way to avoid huge amount of C++ code and leave whatever code fitting in the native C++ code still in the unmanaged world.

Here are the list of the most important features of our C#/.NET PInvoke Interop SDK.

1. Calling from C#/.NET into C++ DLL via PInvoke including all the data type marshaling which is completely automatically handled by the SDK tool.

2. Instantiating C++ class instances from C#/.NET, the life time of the C++ instances are controlled by the C#/.NET code.

3. Invoking all the C++ methods implemented in C++ classes from C#/.NET code, including both static and non-static methods, both of the exported method in the C++ DLL and any of the virtual methods.

4. Accessing C++ fields implemented in C++ classes from C#/.NET code, including both static and non-static fields. The types of the C++ fields exposed in C# code includes all the primitive types, all the C++ classes exported in the DLL, struct types, enum types and the standard C++ classes and instantiated template classes.

5. Subclassing C++ classes from C#/.NET. All the virtual methods in the C++ classes exported from the C++ DLL can be overridden in C#/.NET code. An instance of such a C# class can then be passed to C++ as an object of the native C++ derived class. The native DLL does not see any difference between C# instance and the instance of the C++ derived class.

6. Supporting AnyCPU. If both x86 32 bits and x64 64 bits DLL are available, building a AnyCPU C#/.NET DLL is supported. Both DLLs can be built into the final C#/.NET DLL as embedded resource to support the single C#/.NET DLL to be used in both x86 and x64 running mode. If only the x86 or the x64 DLL is available, then a C#/.NET DLL targeting either x86 or x64 will be built.

7. Wrapping almost all the standard C++ classes to C#/.NET classes, such as std::string, std::wstring, std::iostream, std::fstream, etc. Providing such a library will enable developers to instantiate and access the standard C++ classes without doing any other data type marshaling from their C# code, which is basically impossible without such as C#/.NET library.

8. Automatically recognizing the standard C++ classes used in any of the C++ class interface. If the C++ DLL happens to have a method like,

The type of std::string will be automatically mapped to the corresponding C# class, StdString or simply string depending on how you want to use the method, and there is no extra code or script to write.

9. Automatically recognizing the standard container classes used in the native C++ interface and then export the instantiated template classes from a new supplement DLL to support the C++ class interface, without adding the support of the instantiated template class, any of such class will not be available to the C#/.NET world. For example, if you happened to define a method with a parameter type of std::vector<int> in one of your C++ classes and std::vector<int> is not exported, std::vector<int> class will be exported in a supplement DLL and a corresponding C# wrapper class for std::vector<int> will be created to support accessing the std::vector<int>. The SDK tool can actually go further if you happened to have std::vector<your_struct>, it will export std::vector<your_struct> from the supplement DLL, implement C# version of your_struct and a C# wrapper class for std::vector<your_struct>. In the case that the new supplement requires to access the C++ DLL, it will build a lib file from the C++ DLL and link itself to the library, It is all automatically, developers do not need to do anything manually. This is one of the most important and most powerful features of our C#/.NET PInvoke Interop SDK.

If the SDK Tool discovers that a type of std::vector<int> is used in the C++ classes interface, a C# class named StdIntVector will be generated, and all the types of std::vector<int>*, std::vector<int>&, return type of std::vector<int> will be mapped to StdIntVector.

This great feature releases developers from exporting any template classes when they design their class interface, they will just need to make sure that their non-template classes do get exported in the C++ DLL.

10. Automatically recognizing any of non-standard container template classes in the native C++ DLL interface. As long as the template classes is implemented

inside of header files, any instantiated template classes can be exported in a supplement DLL and a corresponding C# wrapper class will be generated.

11. Automatically recognizing both struct type definitions and enum type definitions and then defining the corresponding struct and enum types in C#. Developers have the choices of keeping the same name or renaming them. When class, struct and enum are defined inside of another struct or class, we usually call them nested class, nested struct and nested enum. Nested data types are fully supported. When those data types are not given names, they are usually called anonymous nested data types which are also fully supported.

12. Automatically recognizing C++ function type definitions and implementing the corresponding delegates in C# code. If a type of function defined as following in the C++ DLL,

A C# delegate of the following will be defined in the C#/.NET wrapper DLL.

13. Automatically recognizing std::function<function_signature> which will then be implemented as a C# class and can be instantiated by using a corresponding C# delegate for that function signature, just like the function type definition.

14. Implementing multiple overrides for the same C++ method. For methods with T* c++ parameter, the SDK’s wrapper generator will implement multiple overrides of the same C++ method in C# code.

A type of T* in C++ does introduce ambiguity in the .NET world because the real meaning of T* is not really clear from .NET without looking into the implementation of C++ method. A workaround of this issue is to implement multiple overrides of the same C++ method and let developers to pick one since they know what the C++ method really does.

For example, if you have the following C++ method in one of your c++ class,

The following C# methods will be implemented to support the method depending on what the C++ method really does, the wrapper generator does not really know what the method really does though.

Among the 4 C# method overrides, the first one is always correct no matter what c++ method really does, but it is inconvenient to use since the developer will have to manually copy the input data to the buffer from the source data. If what the C++ method really does is to accept a byte buffer with another parameter of the number of bytes in the buffer, then the third override is a perfect match. The toolkit will allow you to generate all the possible overrides of the same C++ method, and the developer just need to pick up the one which best fits the original c++ method.

15. Both of the C++ ANSI and Unicode encoded characters and strings are automatically recognized and the corresponding encoding is used to generate the PInvoke signatures.

16. Limited support of pass-by-value when passing an C++ class instance from C#/.NET to C++.

17. The automatically generated source code of the C# wrapper is available. And best of all, the C# wrapper code is very much readable and it is just like any C# code
Developer manually write. It can be modified by developers who know C# PInvoke and data type marshaling.

18. When the C++ source code is changed and a new C++ DLL is generated, all you need to is to rebuild the C#/.NET Wrapper automatically by running the SDK tool against the new C++ DLL and the modified header files one more time, you are done. You can even automate it from post-build command.

Our C#/.NET PInvoke Interop SDK focuses on C++ DLL instead of both C and C++ DLLs since there are existing tools which can wrap a C DLL automatically without developer’s manual involvement. We will add this feature in the future.