Call C++ Library in C#

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);
}
}

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

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

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.

Calling external C library method correctly from C# .Net Core project *On Linux*

The size_t tolen should be IntPtr tolen, because at 64 bits normally sizeof(size_t) == 8. And unclear what idn_action_t and idn_result_t are. Note that the other big difference between linux and windows could be if the long type is used in C. On linux 64 bits, sizeof(long) == 8, while on Windows it depends on the compiler used (and with VC++ it is sizeof(long) == 4)

calling c function from C#

You are looking for P/Invoke.

You do will need a Reference to System.Runtime.InteropServices and then do the following, if your C DLL contains a function called increase_int:

[DllImport("mylib.dll")]
private static extern int increase_int(int in_value);

and use it from your code doing

int newValue = increase_int(oldValue);

Calling C function (Linux) from C# (Windows)

does it matter if my .so file was created in a Linux environment ?

Yes, it matters.

Shared Object (so) files are generated by linkers and contain code. They are platform specific. Even two versions of Linux running on two different CPUs are quite likely to be unable to use the same .so file.

Can I just copy the .so file to a Windows environment and have C# use it without any issues ?

A Windows OS will not use an .so file. It requires .dll files and they are a completely different format ( and in general require completely different code to do the same job ).

I believe it shouldn't matter because .so is a dynamic library and is filled with symbols not dependent on the platform it's created on.

It is not simply a file full of symbols. It is code that will be executed as well. And that code is platform specific.

Call c++ library from c#

Given that you're using a C++ library, I'm assuming it takes advantage of C++ semantics like classes, rather than just exposing procedures. If this is the case, then the way this is typically done is via a manually-created managed C++ interop library.

Basically, you create a managed C++ library in Visual Studio, reference your existing C++ library, and create a managed wrapper around your existing C++ classes. You then reference this (managed) C++ assembly in your C# project and include the original (unmanaged) C++ library in your C# assembly just as a file that gets placed in the build directory.

This is required because there is no way to reference things like C++ classes via P/Invoke (DllImport) calls.

If your base library is just a series of functions, then you can reference that directly in the C# project via P/Invoke functions.

Either way, all of the libraries mentioned above (for the first, the unmanaged C++ library, the managed C++ assembly, and the C# project, or, for the second, the unmanaced C++ library and the C# project) must be included in any project that references them. You cannot statically link the unmanaged library into the managed assembly.

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)



Related Topics



Leave a reply



Submit