Using C# Dll in C++ Code

Using C# dll in C++ code

There are basically two cases to call a .NET DLL from unmanaged code:

  1. The .NET DLL exposes a COM interface. In this case, you can use COM from your C++ code.
  2. The .NET DLL does not expose a COM interface. In this case, you have two possibilities (to make it simple):

    2.a. host the CLR as described here: Loading the Common Language Runtime into a Process

    2.b. write a piece of managed C++ code (another DLL - written in C++/CLI) to wrap the .NET DLL and expose 'old way' DLL exports to unmanaged clients.

I don't specifically know the sharpbox system, but it looks like it's pure .NET and does not expose COM interfaces, so 2.b might be the best way to do it (not so easy...). Maybe it has a REST/Web easier API you could use.

PS: you can also add exports to a .NET DLL. This is described here: Is is possible to export functions from a C# DLL like in VS C++? but it's kinda hacky.

Using C dll in C#

You can use PInvoke

Platform Invocation Services (PInvoke)
allows managed code to call unmanaged
functions that are implemented in a
DLL.

Here is a great tutorial by the NAG (Numerical Algorithms Group) group

using c# dll in project c++

There is more than just COM interop, the MSDN FAQ also lists lesser known methods:

2.2 How do I call .NET assembly from native Visual C++?

There are basically four methods to
call .NET assembly from native VC++
code. Microsoft All-In-One Code Framework has working examples that
demonstrate the methods.

  1. Native VC++ module calls CLR Hosting APIs to host CLR, load and
    call the .NET assembly. (All-In-One
    Code Framework Sample Code:
    CppHostCLR)

  2. If the .NET assembly can be exposed as a COM component, native
    VC++ module can call into the .NET
    assembly through .NET – COM interop.
    (All-In-One Code Framework Sample
    Code: CppCOMClient)

  3. Reverse PInvoke: the managed code call native passing a delegate
    the native code can call back.
    (All-In-One Code Framework Sample
    Code: CSPInvokeDll)

  4. If the module containing native VC++ code is allowed to enable CLR, the native VC++ code can call
    .NET assembly directly through the “It
    Just Works”, or “IJW”, mechanism. (All-In-One Code Framework Sample Code: CppCLIWrapLib)

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.

How use C Dll in C# properly

You need to mark the function in the DLL as exported. There are two ways of doing this. You may either create a .def file and name the exported functions, or add the specifier __declspec(dllexport) to the function signature.

To create a .def file, in Visual Studio with the C DLL project open, right click on "Source Files" and then under "Visual C++" -> "Code", select "Module-Definition File (.def)". In the newly created .def file, you can list the functions you wish to export, like so:

LIBRARY mydll
EXPORTS
function1
function2
function3

Then, when you build the DLL, function1, function2, and function3 are available.

Also, keep in mind that unless you manually specify a calling convention (e.g. int __stdcall function1(int a, int b);), the calling convention is __cdecl by default, and so when you add the line to import the function through P/Invoke, you must also have the attribute CallingConvention = CallingConvention.CDecl. Failing to match calling conventions will cause stack corruption in the calling code.

Calling C# from C

There is more than just COM interop if you want to call into managed code from C or C++. The are also the following lesser known methods (taken from MSDN FAQ):

How do I call a .NET assembly from native Visual C++?

There are basically four methods to
call .NET assembly from native VC++ code:

  1. CLR Hosting API: Native VC++ module calls CLR Hosting APIs to host CLR, load and call the .NET assembly (sample code: CppHostCLR).

  2. COM Interop: If the .NET assembly can be exposed as a COM component, native VC++ module can call into the .NET assembly through .NET – COM interop (sample code: CppCOMClient).

  3. Reverse PInvoke: The managed code calls native code passing a delegate that the native code can call back (sample code: CSPInvokeDll).

  4. C++/CLI: If the module containing native VC++ code is allowed to enable CLR, the native VC++ code can call
    .NET assembly directly (sample code: Consuming C# Library in native C or C++ using C++/CLI)

Call C# dll function from C++/CLI

You must be using c++ CLI, otherwise you could not call DllImport.
If that is the case you can just reference the c# dll.

In c++ CLI you can just do as follows:

using namespace Your::Namespace::Here;

#using <YourDll.dll>

YourManagedClass^ pInstance = gcnew YourManagedClass();

where 'YourManagedClass' is defined in the c# project with output assembly 'YourDll.dll'.

** EDIT **
Added your example.

This is how your example needs to look like in CLI (for clarity I am assuming that G
etResult is not a static function, otherwise you would just call Calculate::GetResult(...)

private: System::Void CalculateResult(int arg1, int arg2)
{
int rez=0;
//Call C++ function from dll
Calculate^ calculate= gcnew Calculate();
rez=calculate->GetResult(arg1,arg2);
}


Related Topics



Leave a reply



Submit