Using C++ Library in C#

Use a C library from C# code

C Libraries compiled for Windows can be called from C# using Platform Invoke.

From MSDN, the syntax of making a C function call is as follows:

[DllImport("Kernel32.dll", SetLastError=true)]
static extern Boolean Beep(UInt32 frequency, UInt32 duration);

The above calls the function Beep in Kernel32.dll, passing in the arguments frequency and duration. More complex calls are possible passing in structs and pointers to arrays, return values etc...

You will need to ensure that the C functions available by the C library are exported appropriately, e.g. the Beep function is likely declared like this:

#define DllExport   __declspec( dllexport )
DllExport bool Beep(unsigned int frequency, unsigned int duration)
{
// C Body of Beep function
}

How to use C-Library in C#

To address alike situation, Microsoft provides attributes, assembly, and marshaling to offer interoperability between managed-unmanaged code(not .net aware/running outside the clr boundaries) and managed-legacy COM.

Investigate the use of dynamics and the (Dynamic language runtime- DLR) which should be more than fine.

code example (using kernel32.dll) as an example of calling unmanaged code from a managed context

[DllImport("kernel32.dll", EntryPoint="MoveFile",
ExactSpelling=false, CharSet=CharSet.Unicode,
SetLastError=true)]
static extern bool MoveFile(string sourceFile, string destinationFile);

//calling the function
static void Main()
{
MoveFile("sheet.xls", @"c:\sheet.xls");
}

check this pdf also: http://www.nag.com/IndustryArticles/Calling_C_Library_DLLs_from_C_Sharp.pdf

Call C++ library in C#

  1. DllImport - http://msdn.microsoft.com/en-us/library/aa984739(VS.71).aspx
  2. Wrapper class - http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/67cc9eea-a4fe-48bd-b8d5-f3c8051ba896

Using c++ library in c#

If it is a "normal" DLL (not COM, not managed C++), you cannot add a reference like this. You have to add p/invoke signatures (external static method definitions) for the exports you want to call in your DLL.

[DllImport("yourdll.dll")]
public static extern int ExportToCall(int argument);

Have a look at the DllImport attribute in the online help.

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.

Is it possible to call a C function from C#.Net

The example will be, for Linux:

1) Create a C file, libtest.c with this content:

#include <stdio.h>

void print(const char *message)
{
printf("%s\\n", message);
}

That’s a simple pseudo-wrapper for printf. But represents any C function in the library you want to call. If you have a C++ function don’t forget to put extern C to avoid mangling the name.

2) create the C# file

using System;

using System.Runtime.InteropServices;

public class Tester
{
[DllImport("libtest.so", EntryPoint="print")]

static extern void print(string message);

public static void Main(string[] args)
{

print("Hello World C# => C++");
}
}

3) Unless you have the library libtest.so in a standard library path like “/usr/lib”, you are likely to see a System.DllNotFoundException, to fix this you can move your libtest.so to /usr/lib, or better yet, just add your CWD to the library path: export LD_LIBRARY_PATH=pwd

credits from here

EDIT

For Windows, it's not much different.
Taking an example from here, you only have yo enclose in your *.cpp file your method with extern "C"
Something like

extern "C"
{
//Note: must use __declspec(dllexport) to make (export) methods as 'public'
__declspec(dllexport) void DoSomethingInC(unsigned short int ExampleParam, unsigned char AnotherExampleParam)
{
printf("You called method DoSomethingInC(), You passed in %d and %c\n\r", ExampleParam, AnotherExampleParam);
}
}//End 'extern "C"' to prevent name mangling

then, compile, and in your C# file do

[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]

public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);

and then just use it:

using System;

using System.Runtime.InteropServices;

public class Tester
{
[DllImport("C_DLL_with_Csharp.dll", EntryPoint="DoSomethingInC")]

public static extern void DoSomethingInC(ushort ExampleParam, char AnotherExampleParam);

public static void Main(string[] args)
{
ushort var1 = 2;
char var2 = '';
DoSomethingInC(var1, var2);
}
}


Related Topics



Leave a reply



Submit