C++/Cli Wrapper for Native C++ to Use as Reference in C#

C++/CLI wrapper for native C++ to use as reference in C#

Ok, tutorial. You have a C++ class NativeClass that you want to expose to C#.

class NativeClass { 
public:
void Method();
};

1) Create a C++/CLI project. Link to your C++ library and headers.

2) Create a wrapper class that exposes the methods you want. Example:

#include "NativeClass.h"

public ref class NativeClassWrapper {
NativeClass* m_nativeClass;

public:
NativeClassWrapper() { m_nativeClass = new NativeClass(); }
~NativeClassWrapper() { this->!NativeClassWrapper(); }
!NativeClassWrapper() { delete m_nativeClass; }
void Method() {
m_nativeClass->Method();
}
};

3) Add a reference to your C++/CLI project in your C# project.

4) Use the wrapper type within a using statement:

using (var nativeObject = new NativeClassWrapper()) {
nativeObject.Method();
}

The using statement ensures Dispose() is called, which immediately runs the destructor and destroys the native object. You will otherwise have memory leaks and probably will die horribly (not you, the program). Note : The Dispose() method is magically created for you.

How to call a C# library from Native C++ (using C++\CLI and IJW)

I found something that at least begins to answer my own question. The following two links have wmv files from Microsoft that demonstrate using a C# class in unmanaged C++.

This first one uses a COM object and regasm: http://msdn.microsoft.com/en-us/vstudio/bb892741.

This second one uses the features of C++/CLI to wrap the C# class: http://msdn.microsoft.com/en-us/vstudio/bb892742. I have been able to instantiate a c# class from managed code and retrieve a string as in the video. It has been very helpful but it only answers 2/3rds of my question as I want to instantiate a class with a string perimeter into a c# class. As a proof of concept I altered the code presented in the example for the following method, and achieved this goal. Of course I also added a altered the {public string PickDate(string Name)} method to do something with the name string to prove to myself that it worked.

wchar_t * DatePickerClient::pick(std::wstring nme)
{
IntPtr temp(ref);// system int pointer from a native int
String ^date;// tracking handle to a string (managed)
String ^name;// tracking handle to a string (managed)
name = gcnew String(nme.c_str());
wchar_t *ret;// pointer to a c++ string
GCHandle gch;// garbage collector handle
DatePicker::DatePicker ^obj;// reference the c# object with tracking handle(^)
gch = static_cast<GCHandle>(temp);// converted from the int pointer
obj = static_cast<DatePicker::DatePicker ^>(gch.Target);
date = obj->PickDate(name);
ret = new wchar_t[date->Length +1];
interior_ptr<const wchar_t> p1 = PtrToStringChars(date);// clr pointer that acts like pointer
pin_ptr<const wchar_t> p2 = p1;// pin the pointer to a location as clr pointers move around in memory but c++ does not know about that.
wcscpy_s(ret, date->Length +1, p2);
return ret;
}

Part of my question was: What is better? From what I have read in many many efforts to research the answer is that COM objects are considered easier to use, and using a wrapper instead allows for greater control. In some cases using a wrapper can (but not always) reduce the size of the thunk, as COM objects automatically have a standard size footprint and wrappers are only as big as they need to be.

The thunk (as I have used above) refers to the space time and resources used in between C# and C++ in the case of the COM object, and in between C++/CLI and native C++ in the case of coding-using a C++/CLI Wrapper. So another part of my answer should include a warning that crossing the thunk boundary more than absolutely necessary is bad practice, accessing the thunk boundary inside a loop is not recommended, and that it is possible to set up a wrapper incorrectly so that it double thunks (crosses the boundary twice where only one thunk is called for) without the code seeming to be incorrect to a novice like me.

Two notes about the wmv's. First: some footage is reused in both, don't be fooled. At first they seem the same but they do cover different topics. Second, there are some bonus features such as marshalling that are now a part of the CLI that are not covered in the wmv's.

Edit:

Note there is a consequence for your installs, your c++ wrapper will not be found by the CLR. You will have to either confirm that the c++ application installs in any/every directory that uses it, or add the library (which will then need to be strongly named) to the GAC at install time. This also means that with either case in development environments you will likely have to copy the library to each directory where applications call it.

C++/CLI wrapper for native C++ dll

I have found the error (System.AccessViolationException):

I'm using an other object in the unmanaged code without initialization (null object -> only declared)!

Init the object with new() and all should run properly!

Pass int by reference from C++/CLI to C#

C#:

class MyClass 
{
public static string GetNameAndValue(out int value);
}

C++/CLI:

int value;
String^ x = MyClass::GetNameAndValue(value);

C++/CLI wrapper:

CString GetNameAndValue(int* value)
{
String^ x = MyClass::GetNameAndValue(*value);
return CString(x);
}

C++/CLI wrapper 2:

CString GetNameAndValue(int& value)
{
String^ x = MyClass::GetNameAndValue(value);
return CString(x);
}

It's the same for C# "ref".

Linking Native/C++ DLL to Managed C++/CLI Wrapper in Visual Studio 2010

Your first error 'populationwin32' : is not a class or namespace name means, the compiler has no knowledge about this namespace.

Add an

#include "PopulationWin32.h"

to make this known to Visual Studio.

You also must add the path to your include file, so the compiler can find it. This is described here VC++ Directories, Projects and Solutions, Options Dialog Box and here The #include Directive, for example.

C# to c++/cli to unamanged c++ ref

If the value update needs to be propagated back to the C# code (so the ref keyword makes sense) then you have to declare the C++/CLI argument as int% result. The exact syntactical equivalent of int& in native C++.

However, it might be an "interior pointer" at runtime. You could for example pass a field of a class object in your C# code. Stored on the GC heap and that is an important detail. The GC might run while the native code is running (triggered by another thread for example) and move the object while it compacts the heap. That would make the pointer invalid. The C++/CLI compiler can't let that happen and will complain loudly if you try to pass result directly to the native function. The basic reason why the C++/CLI designers chose different symbols for managed references (^ vs * and % vs &).

Providing a stable pointer is required, the simplest way to do so is by passing a pointer to a value that is not stored on the GC heap. Like this:

public:
void MethodCLI(int% result)
{
int temp = result;
UnmanagedFunction(&temp);
result = temp;
}

The pin_ptr keyword becomes useful if you need to pass an object instead of a value, it temporarily pins the passed object so the GC can't invalidate the pointer.



Related Topics



Leave a reply



Submit