.net 如何从非托管代码调用托管代码?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/225277/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 10:23:58  来源:igfitidea点击:

How to call managed code from unmanaged code?

.netc++-cliinteropclrunmanaged

提问by Hanan

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.

我想从非托管 C++ 调用我的 .NET 代码。我的流程入口点是基于 .NET 的,所以我不必担心托管 CLR。我知道它可以使用 .NET 对象的 COM 包装器来完成,但我想访问托管类的各个静态方法,所以 COM 不是我最短/最简单的路线。

采纳答案by Rasmus Faber

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).

假设您正在谈论真正的非托管代码 - 不仅仅是在使用 /clr 编译的混合模式程序集中运行的本机 C++ - 最简单的方法是在 C++/CLI 中为您的 .NET 代码创建包装器。然后,您只需使用 __declspec(dllexport) 标记即可导出 C++/CLI 方法。

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.

或者,如果您可以控制非托管代码的调用,则可以将函数指针编组到 .NET 方法并将它们传递给非托管代码。

回答by MajesticRa

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

看看这个解决方案:https: //sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports该解决方案允许通过使用 [DllExport] 属性装饰您的函数(与 P/Invoke DllImport 相反)从 C 调用 C# 函数.

Exmaple:

例子:

C# code

C# 代码

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?

如何在非托管项目中包含 dll?

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)

您必须链接到编译 C# 代码时生成的 .lib 文件(https://msdn.microsoft.com/en-us/library/ba1z7822.aspx?f=255&MSPPError=-2147217396

回答by Stu Mackellar

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

查看GCHandle类和 gcroot 关键字,它提供了一个类型安全的、模板化的 GCHandle 包装器。

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

您可以使用它们在本机代码中保存对 CLR 对象(或装箱值)的引用。

MSDN has a basic tutorial here.

MSDN 有一个基本教程here

回答by JaredPar

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。如果你用谷歌搜索反向 pinvoke,你会得到很多有用的条目。我认为下面有一个很好的快速和肮脏的例子。

PInvoke-Reverse PInvoke and __stdcall - __cdecl

PInvoke-反向 PInvoke 和 __stdcall - __cdecl

回答by Aamir

Your calling code is C++ with /clrenabled. Right?

您的调用代码是/clr启用的C++ 。对?

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

如果是,那么您可以简单地使用 using 语句在您的代码中使用您的 .NET dll。就像是:

#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.

如果你想让这个 obj 成为你的类的数据成员,使用 gcroot 是要走的路。