从C中调用C#

37

有人尝试过从C模块调用C#模块吗?我在互联网上搜索了一下,但没有找到好的例子。虽然很多网站说可以使用COM互操作性,但是没有找到一个恰当的例子或文章来解释它。

如果有人能帮忙解决这个问题,那就太好了。

谢谢, Sveerap

4个回答

30

如果你想从C或C++调用托管代码,不仅仅局限于COM互操作。还有以下一些较少人知的方法(源自MSDN FAQ):

如何在本机Visual C++中调用.NET程序集?

基本上有四种方法可以实现在本机VC++代码中调用.NET程序集:

  1. CLR托管API:本机VC++模块通过调用CLR托管APIs来托管CLR、加载和调用.NET程序集(示例代码:CppHostCLR)。

  2. COM互操作:如果.NET程序集可以作为COM组件公开,本机VC++模块可以通过.NET-COM互操作调用.NET程序集(示例代码:CppCOMClient)。

  3. 反向PInvoke:托管代码调用本机代码时,传递一个委托,本机代码可以回调该委托(示例代码:CSPInvokeDll)。

  4. C++/CLI:如果包含本机VC++代码的模块允许启用CLR,本机VC++代码可以调用包含托管代码的.NET程序集。

.NET程序集直接调用(示例代码:使用C++/CLI在本地C或C++中调用C#库


谢谢您的帮助,我会仔细研究它们并发布我的回复。 - sveerap
1
谢谢,我尝试了COM互操作并完成了一个类似于hello world的应用程序。 - sveerap
One Code和CLR Hosting APIs的链接已经失效。你能提供最新的更新吗?(我找不到正确的链接) - Robot Mess

20

以下是解决方案。该解决方案允许在一个 C# 函数上使用 [DllExport] 属性,从而可以通过 C 调用该函数(与 P/Invoke DllImport 相反)。

https://sites.google.com/site/robertgiesecke/Home/uploads/unmanagedexports

C# 代码

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

C 代码

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

如下评论所述:

该链接的作者在编译过程中提供了一个CLR IL预处理器作为附加步骤。由于装配件在Windows上使用相同的二进制容器格式(DLL),如果您手动将.Net函数偏移量添加到IL中的vtable(dll的导出列表)中,则Windows聪明地调用CLR来运行从C中调用的代码。但是,这会带来开销。这是一个未经宣传的功能。这就是C++/CLI中混合托管库的工作原理。要使用它,请通过Nuget添加它。您的MSBuild项目文件中添加的额外目标将提供IL预处理步骤。


7
我读了那个链接,但他并没有真正提供使用的示例。在C项目中加载C#(dll?)代码,需要做什么?你需要使用LoadLibrary FreeLibrary等吗? - weston
有助于学生的是一个示例 .csproj 文件和 MSBUILD 指令,这将允许学生构建示例应用程序。 - V. V. Kozlov
我认为这个程序不适用于最新的.NET,因为它仍然引用3.5版本,或者至少我无法让它工作 =(。在Win10中,我认为一个解决方法是下载3.5框架。我现在会尝试一下。 - Gaspa79
我一开始没有意识到这是使用的 UnmanagedExports 库而不是核心库代码。 - Lyndon Gingerich

8

谢谢,我尝试了COM互操作,并成功创建了一个类似于Hello World的应用程序。 - sveerap

1

使用CoreRT,您还可以选择从C#代码构建本地库,并从C中调用它们。

这里有一个示例。

编辑:CoreRT已移动到runtimelab功能NativeAOT。更新链接。


我使用了您提供的链接并成功进行了一些测试。它有效。谢谢。 - Roberto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接