How to call managed code from unmanaged code?
Asked Answered
E

6

22

I want to call my .NET code from unmanaged C++. My process entrypoint is .NET based, so I don't have to worry about hosting the CLR. I know it can be done using COM wrappers for .NET objects, but I would like to access individual static methods of managed classes, so COM isn't my shortest/easiest route.

Extrabold answered 22/10, 2008 at 11:9 Comment(1)
possible duplicate of Exporting dll functions to unmanaged programsGorey
T
7

Assuming you are talking about real unmanaged code - not just native C++ running in a mixed-mode assembly compiled with /clr - the easiest way is to create a wrapper to your .NET code in C++/CLI. You can then export the C++/CLI methods by just marking them with __declspec(dllexport).

Alternatively, if you have control over the invocation of the unmanaged code, you can marshal function-pointers to your .NET methods and pass them to the unmanaged code.

Tenorio answered 22/10, 2008 at 11:27 Comment(2)
A very abstract answer which surely is not useful for a beginner who asks this question. Here the code sample is missing!Emanuele
@Elmue: Have to disagree. Interfacing C# with C++ is certainly not a beginner topic in the first place. This answer gives all the keywords necessary for further reading and outline for the necessary steps.Halfblood
D
26

Look at this solution: https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports The solution allows to call C# function from C by decorating your function with [DllExport] attribute (opposite of P/Invoke DllImport).

Exmaple:

C# code

class Test
{
     [DllExport("add", CallingConvention = CallingConvention.StdCall)]
     public static int Add(int left, int right)
     {
         return left + right;
     } 
}

C code:

 extern "C" int add(int, int);

 int main()
 {
      int z = add(5,10);
      printf("The solution is found!!! Z is %i",z);
      return 0;
 }

Output:

The solution is found!!! Z is 15

Update: There is a question and a good answer in comments:

How do I include the dll in the unmanaged project?

You have to link to the .lib file that is generated upon compiling your C# code (https://msdn.microsoft.com/en-us/library/ba1z7822.aspx?f=255&MSPPError=-2147217396)

Domingodominguez answered 22/7, 2011 at 20:9 Comment(2)
How do I include the dll in the unmanaged project? Is there an example project somewhere (e.g. for visual studio)?Caudle
@Caudle I know it's been years but I'm putting this here so someone else can see it in the future. The way I did it was compile the .cs project using x64/x86. I then linked to the .lib file that was generated in my native c++ project. In the header file I referenced the method signature: extern "C" { void ExportedMethodName(); } Then used it normally.Cystocarp
T
7

Assuming you are talking about real unmanaged code - not just native C++ running in a mixed-mode assembly compiled with /clr - the easiest way is to create a wrapper to your .NET code in C++/CLI. You can then export the C++/CLI methods by just marking them with __declspec(dllexport).

Alternatively, if you have control over the invocation of the unmanaged code, you can marshal function-pointers to your .NET methods and pass them to the unmanaged code.

Tenorio answered 22/10, 2008 at 11:27 Comment(2)
A very abstract answer which surely is not useful for a beginner who asks this question. Here the code sample is missing!Emanuele
@Elmue: Have to disagree. Interfacing C# with C++ is certainly not a beginner topic in the first place. This answer gives all the keywords necessary for further reading and outline for the necessary steps.Halfblood
E
6

Take a look at the GCHandle class and the gcroot keyword, which provides a typesafe, templated wrapper around GCHandle.

You can use these to hold a reference to a CLR object (or a boxed value) in native code.

MSDN has a basic tutorial here.

Ermina answered 22/10, 2008 at 11:44 Comment(1)
Note that this requires /clr to be enabled.Tenorio
T
4

I believe you are looking for Reverse PInvoke. If you google for reverse pinvoke you'll get a lot of helpful entries. I think the following has a good quick and dirty example.

PInvoke-Reverse PInvoke and __stdcall - __cdecl

Thibodeau answered 30/10, 2008 at 17:27 Comment(0)
F
2

Your calling code is C++ with /clr enabled. Right?

If yes, then you can simply use the using statement to use your .NET dll in your code. Something like:

#using <Mydll.dll>

and then you can simply make the objects of your managed classes like:

MyNameSpace::MyClass^ obj = new MyNameSpace::MyClass();

If you want to make this obj a data member of your class the using gcroot is the way to go.

Fournier answered 22/10, 2008 at 12:4 Comment(3)
useful, but he did say "from unmanaged C++". /clr stops it being unmanaged.Aureliaaurelian
I think this is what he specifically mentioned. <i>My process entrypoint is .NET based, so I don't have to worry about hosting the CLR</i>Fournier
He might also have meant that he is P/Invoking into a completely unmanaged C++ dll and want to call back into the CLR again.Tenorio
R
1

Find nice way here Using C# from native C++ with the help of C++/CLI after integration to different solution found also these changes:

AdditionalIncludeDirectories ...YahooAPIWrapper

AdditionalDependencies ...YahooAPIWrapper.lib

And relations to both projects, was able to open C# form by thread in last DLL and send info from native C++, only ...APIWrapper.h include needed - should be done way better, but works ;-)

public YahooAPI()
{
    new Thread(() =>
    {
        Thread.CurrentThread.IsBackground = true;
        ShowForm();
    }).Start();
}

private static Form1 form = null;
public static void ShowForm()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    form = new Form1();
    Application.Run(form);
}

public void SendValues(bool[] values)
{
    if (form != null && form.ready) ...
}

ready is my bool member set when form initialization finished

Raimondo answered 7/8, 2021 at 12:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.