Answered by:

Create a Wrapper DLL to access C++ lib classes in C#

Question

I need to access classes from a C++ project in a C# project. After a bit of research, it looks like the solution is to create a wrapper around the C++ library, create a DLL, then use it in the new C# project.

All the examples I have seen reference just small static functions. What can I do, or where can I go, to get a good example of what I'm trying to accomplish?

you cannot use STL containers in managed code directly, to pass STL containers back and forth between managed and unmanaged code, you need to do the conversion yourself, (managed arrary to vector, hashtable to map, etc.), in other words, you can not call a method that takes STL container as parameter in your managed code, a workaround is to create a method that takes managed collections as its parameters and convert the managed collections to STL containers inside the method.

ryoung786 wrote:

Using this concept, should I treat all other complex datatypes as Object handles (Object^)? And then try and unbox them within the wrapper method? I really need this functionality, as I must pass collections back and forth (set, vector, lists, etc).

To go back to the question, you cannot use something like "vector ^vec", as you may have already learned, object handle (^) simply means the object is allocated in managed heap, you cannot allocate a vector in managed heap so you cannot use handle for it. The code "String ^ str = "some string literal";" works because String is System:tring not std:tring.

I have followed the great links and read up on the subject some more, but have run into a new problem. My wrapper class is written in C++/CLI, and the program I use it in is written in C#. The methods with primitive data types are all visible and can be used without a problem (parameters and return types int, double, etc), but those with more complex types cannot be called (parameters like string, set, etc).

A solution for the strings was to convert my wrapper classes from "public ref class ClassXXX" to "public __gc class ClassXXX", but I'm not clear why. Also, I need a broader solution that applies to other data types as well.

In summary, what can I do to make my return types and parameters work both with the wrapper and C#?

OK, a little more probing and here's what I know now. __gc style is older syntax used in Managed C++, and must be compiled with the /clrldSyntax switch, whereas ref and other keywords are part of the newer C++/CLI.

Strings are fine now as well, since I discovered (after way too much searching!) what the ^ character was. For example, the code

Code Snippet

String ^ str = "some string literal";

assigns a new String handle. This is also a basic datatype that can be passes back and forth between the Wrapper class and C#.

Using this concept, should I treat all other complex datatypes as Object handles (Object^)? And then try and unbox them within the wrapper method? I really need this functionality, as I must pass collections back and forth (set, vector, lists, etc).

you cannot use STL containers in managed code directly, to pass STL containers back and forth between managed and unmanaged code, you need to do the conversion yourself, (managed arrary to vector, hashtable to map, etc.), in other words, you can not call a method that takes STL container as parameter in your managed code, a workaround is to create a method that takes managed collections as its parameters and convert the managed collections to STL containers inside the method.

ryoung786 wrote:

Using this concept, should I treat all other complex datatypes as Object handles (Object^)? And then try and unbox them within the wrapper method? I really need this functionality, as I must pass collections back and forth (set, vector, lists, etc).

To go back to the question, you cannot use something like "vector ^vec", as you may have already learned, object handle (^) simply means the object is allocated in managed heap, you cannot allocate a vector in managed heap so you cannot use handle for it. The code "String ^ str = "some string literal";" works because String is System:tring not std:tring.