Can You Call a C# Dll from a C Dll

Can you call a C# DLL from a C DLL?

The most straight forward way of doing this is to expose one of the C# classes in your C# DLL as a COM object, and then create an instance of it from your C/C++ DLL. If that isn't an acceptable option, you'd need to create a mixed-mode C++ DLL (which contains both managed and unmanaged code). Your C/C++ DLL can call exported functions in your mixed-mode DLL, which can in turn forward the calls on to your C# class.

Call function from DLL?

Add the DLL via the solution explorer - right click on references --> add reference then "Browse" to your DLL - then it should be available.

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

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

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 a C# method/function from a C++ DLL (which is loaded from C# with Dllimport)

So ok, after a few test on starting back to zero, I finally managed to get this callback running !

So here is the test project I created to use the callback.

On C++ side

export.def

LIBRARY TestCallBack
EXPORTS
callCSharpFunction

TestCallBack.cpp

__declspec(dllexport) void callCSharpFunction ( void *fctPointer(int) )
{
fctPointer(123456);
}

This C++ project is being built as a "DLL" file and put within a "lib" project in the C#'s project folder.

On C# side

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleApplication1
{
class Program
{
// Set the library path
const string dllFilePath =
"C:\\PathToProject\\TestCallBack\\ConsoleApp\\lib\\TestCallBack.dll";

// This is the delegate type that we use to marshal
// a function pointer for C to use. You usually need
// to specify the calling convention so it matches the
// convention of your C library. The signature of this
// delegate must match the signature of the C function
// pointer we want to use.
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
delegate void FunctionPointer( int nb);

// This is the function we import from the C library.
//[DllImport(dllFilePath)]
[DllImport(dllFilePath, CallingConvention = CallingConvention.Cdecl)]
public static extern void callCSharpFunction(IntPtr fctPointer);

// This is the placeholder for the function pointer
// we create using Marshal.GetFunctionPointerForDelegate
static IntPtr FctPtr;

// This is the instance of the delegate to which our function
// pointer will point.
FunctionPointer MyFunctionPointer;

// This calls the specified delegate using the C library.
void CallFunctionPointer(FunctionPointer cb)
{
// make sure the delegate isn't null
if (null == cb) throw new ArgumentNullException("cb");

// set our delegate place holder equal to the specified delegate
MyFunctionPointer = cb;

// Get a pointer to the delegate that can be passed to the C lib
FctPtr = Marshal.GetFunctionPointerForDelegate(MyFunctionPointer);

// call the imported function with that function pointer.
callCSharpFunction(FctPtr);
}

static void Main(string[] args)
{
// This is the instance of the delegate to which our function
// pointer will point.
FunctionPointer printInConsoleDelegate;

// Create the delegate object "MyFunctionPointer" that references
printInConsoleDelegate = new FunctionPointer(printInConsole);

// Get a pointer to the delegate that can be passed to the C lib
IntPtr printInConsolePtr =
Marshal.GetFunctionPointerForDelegate(printInConsoleDelegate);

Console.WriteLine(
"Call C++ which's calling back C# func \"printInConsole\"");

// Call C++ which calls C#
callCSharpFunction(printInConsolePtr);

// Stop the console until user's pressing Enter
Console.ReadLine();
}

public static void printInConsole(int nb)
{
// Write the parameter in the console
Console.WriteLine("value = " + nb + "; ");
}
}
}


Related Topics



Leave a reply



Submit