从 C++ 调用 C# 代码

Posted

技术标签:

【中文标题】从 C++ 调用 C# 代码【英文标题】:Calling C# code from C++ 【发布时间】:2010-10-21 04:26:57 【问题描述】:

我需要能够从 C++ 调用任意 C# 函数。 http://www.infoq.com/articles/in-process-java-net-integration 建议使用 ICLRRuntimeHost::ExecuteInDefaultAppDomain() 但这仅允许我调用具有这种格式的方法:int method(string arg)

调用任意 C# 函数的最佳方法是什么?

【问题讨论】:

任意代码是什么意思?可实现的最细粒度不是在功能级别吗? 从.NET 5.0开始,就有了使用共享库的跨平台方式:请看this answer。 【参考方案1】:

C++ 应用程序可以通过多种方式调用 C# DLL 中的函数。

    使用 C++/CLI 作为中间 DLL http://blogs.microsoft.co.il/sasha/2008/02/16/net-to-c-bridge/ 反向 P/Invoke http://tigerang.blogspot.ca/2008/09/reverse-pinvoke.html http://blogs.msdn.com/b/junfeng/archive/2008/01/28/reverse-p-invoke-and-exception.aspx 使用 COM http://msdn.microsoft.com/en-us/library/zsfww439.aspx 使用 CLR 托管 (ICLRRuntimeHost::ExecuteInDefaultAppDomain()) http://msdn.microsoft.com/en-us/library/dd380850%28v=vs.110%29.aspx http://msdn.microsoft.com/en-us/library/ms164411%28v=vs.110%29.aspx https://***.com/a/4283104/184528 进程间通信 (IPC) How to remote invoke another process method from C# application http://www.codeproject.com/Tips/420582/Inter-Process-Communication-between-Csharp-and-Cpl 编辑:托管 HTTP 服务器并通过 HTTP 动词调用(例如 REST 样式 API)

【讨论】:

这 5 种方法中哪一种更可取,为什么?这将是有效的 如果你正在寻找一个跨平台的解决方案(所以 COM 或 C++ \clr 是不可能的),并且可以容忍一个扁平的 API(没有 OOP 语法,à la C API),there is (将是).NET 5 中的解决方案:使用它,您可以从 C# 代码创建一个 DLL,该 DLL 可以在 Linux 上从 C 或 C++ 使用(允许处理 C# 对象,就像在 C API 中为 C++ 代码所做的那样) .【参考方案2】:

使用 /clr 标志编译您的 C++ 代码。这样,您就可以相对轻松地调用任何 .NET 代码。

例如:

#include <tchar.h>
#include <stdio.h>

int _tmain(int argc, _TCHAR* argv[])

    System::DateTime now = System::DateTime::Now;
    printf("%d:%d:%d\n", now.Hour, now.Minute, now.Second);

    return 0;

这算作“C++”吗?好吧,这显然不是标准 C++ ...

【讨论】:

那么它不再是 C++ 调用 C#,而是 C++/CLI 调用 C# - 你已经回避了这个问题。 C++ 与 C++/CLI 是一个非常重要的区别,不应忽视。 你不能导出 C++/CLI 函数,以便它们可以从普通 C++ 代码调用吗? Dan,您能否发布一个示例来展示如何从 C++/CLI 调用 C# 代码? C++/CLI 可以像调用“常规”C++ 函数一样调用任何 C# 函数。添加您的参考资料,/clr 就可以了。 “这算作 C++ 吗?嗯,它显然不是标准 C++”...关键是普通的 C/C++ 代码应该能够调用调用 C# 的 C++/CLI。看到它是如何工作的,我对这个解决方案非常满意。 @Filip:不是;如果你只是添加/clr,你仍然会得到unsafe 代码,这真的限制了你在很多地方C# 非常有用(例如Windows Phone、Silverlight、ASP.NET,任何其他不受信任的代码正在执行...... )【参考方案3】:

见DllExport。

IOW:DllImport 的工作方式完全相反。

https://github.com/3F/DllExport

它支持 Windows,并且正在开发跨平台支持。

C# 代码(我们从 C++ 中调用):

[DllExport]
public static int _add(int a, int b)

    return a + b;


[DllExport]
public static bool saySomething()

    DialogResult dlgres = MessageBox.Show(
        "Hello from managed environment !",
        ".NET clr",
        MessageBoxButtons.OKCancel
    );

    return dlgres == DialogResult.OK;

C++ 代码(调用之前的 C# 代码):

typedef int(__cdecl *_add)(int a, int b);
typedef bool(__cdecl *saySomething)();

auto pAdd = (_add)GetProcAddress(lib, "_add");
int c = pAdd(5, 7);

auto pSaySomething = (saySomething)GetProcAddress(lib, "saySomething");
bool dlgres = pSaySomething();

还有一个带有演示的 YouTube 视频 Managed & Unmanaged; PInvoke; [ Conari vs DllExport]。老实说,文档还不够完美,但不要让你失望:YouTube 视频非常棒。

这个项目的灵感来自另一个project from Robert Giesecke,它有220,000 downloads on NuGet。

有趣的事实:一些 Python 库已经使用它来实现 C++ 和 C# 的混合功能。

最后,感谢 Robert Giesecke 和 Denis Kuzmin,他们的工作非常出色!

【讨论】:

感谢您的捐赠,托尔米!这确实有助于继续开发和支持我的免费产品。 CoreCLR 支持 我计划在我的时间里尽可能通过第 90 期进行审查。关注新闻。 啊,是的,与糟糕的文档相比,每个人都可以使用complete demo project 和其他相关的screencasts,正如您已经注意到的那样。但总的来说,每个人都可以改进我们的文档!我个人仅通过Conari 等添加了关于我们的 DllExport 工具和相关 PInvoke 功能的基本内容。因为我更喜欢使用代码而不是文档:)【参考方案4】:

如果您不关心您的 C++ 程序(或其中的一部分)是否使用 /clr 编译,您可以使用 C++/CLI 简单地调用任何 .NET 代码(只要添加对它的引用)。 Try out this article.

编辑:这里是a nice tutorial

另一条路线是让您的 C# 代码公开为 COM。

【讨论】:

好答案,坏教程。如果可能,请链接到更好的教程:)【参考方案5】:

最简单的方法是使用 COM 互操作。

【讨论】:

IJW(C++ 互操作)比 COM 互操作容易得多。【参考方案6】:

您可以在编译成 DLL 的 C# 代码周围使用COM callable wrapper。

【讨论】:

【参考方案7】:

作为一种替代方法,您可以使用Lua 来实例化 CLR 对象、执行并返回结果。

【讨论】:

【参考方案8】:

来自微软:Write a custom .NET Core host to control the .NET runtime from your native code。

IOW:在 Windows 和 Linux 上从 C++ 调用 C#。

有sample code on GitHub。

此示例代码是跨平台的,它允许从 Linux 和 Windows 上的任何 C++ 应用程序调用 .NET Core 中的 C# 代码。

老实说,与其他 DllExport 答案相比,此解决方案似乎相当复杂。 C++ 代码在扫描资源和入口点等方面做了很多繁重的工作。这个答案的一个论点可能是它是跨平台的。但是,另一个DllExport 答案也是跨平台的,并且使用起来更简单。

【讨论】:

以上是关于从 C++ 调用 C# 代码的主要内容,如果未能解决你的问题,请参考以下文章

使用 c# 中的 c++ 引用中的引用从 C# 错误调用 C++ 代码

从 c# 代码调用带有 void *parameter 的本机 c++ 函数

从 C++ 调用 C#

如何编写我的 C++ 函数以便我可以从 C# 调用它?

从 C# 调用 C++ 代码 [重复]

在 WP8 中从 C++ 代码调用 C# 方法