从非托管代码调用托管代码

时间:2008-10-22 11:09:34

标签: .net interop clr unmanaged

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

谢谢!

6 个答案:

答案 0 :(得分:18)

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

<强>〔实施例:

C#代码

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

C代码:

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

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

输出:

The solution is found!!! Z is 15

更新:评论中有一个问题和一个好答案:

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

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

答案 1 :(得分:6)

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

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

答案 2 :(得分:6)

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

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

MSDN有一个基础教程here

答案 3 :(得分:3)

我相信你正在寻找Reverse PInvoke。如果你谷歌反向pinvoke你会得到很多有用的条目。我认为以下是一个很好的快速和肮脏的例子。

PInvoke-Reverse PInvoke and __stdcall - __cdecl

答案 4 :(得分:1)

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

如果是,那么您只需使用using语句在代码中使用.NET dll即可。类似的东西:

#using <Mydll.dll>

然后您可以简单地创建托管类的对象,如:

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

如果你想让这个obj成为你班级的数据成员,可以使用gcroot。

答案 5 :(得分:0)

在集成到不同的解决方案后,在这里找到不错的方法 Using C# from native C++ with the help of C++/CLI 也发现了这些变化:

其他IncludeDirectories ...YahooAPIWrapper

其他依赖项 ...YahooAPIWrapper.lib

与两个项目的关系,能够在最后一个 DLL 中通过线程打开 C# 表单并从本机 C++ 发送信息,只需要 ...APIWrapper.h 包含 - 应该做得更好,但有效;-)

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 是表单初始化完成时设置的 bool 成员