从C++调用C#,反向P/Invoke,混合模式DLL和C++/CLI

17

据我理解,我可以使用反向 P/Invoke 从 C++ 调用 C#。 反向 P/Invoke 简单来说就是:

  1. 创建托管 (C#) 类。
  2. 创建一个 C++/CLI(以前的托管 C++)类库项目。 使用它来调用托管的 C# 类(可能通过引用)。
  3. 从本机 C++ 调用 C++/CLI 代码。

问题:

  1. 这正确吗?
  2. 在步骤2中创建的 DLL 是否称为混合模式 DLL?
  3. 就 MS 而言,C++/CLI 是否完全取代了托管 C++?
  4. 是否完全避免使用 COM 采用此方法?
  5. CLR 何时由谁创建和运行?

提前致谢


1
在这种情况下,您会发现gcroot<>模板类非常有用。 - Greg D
3个回答

23

以下是我所知道的答案:

  1. 是的
  2. 是的,它是一个混合模式的DLL(实际上,您可以将您的本机C++项目的一个文件转换为托管代码,并在该文件中创建这个C++/CLI类,并直接从该文件调用代码。您甚至不需要一个单独的DLL来完成这个过程。
  3. C++/CLI和Managed C++表示相同的东西。唯一的区别是,在较早的版本(Visual Studio 2003之前),它被称为Managed C++。后来,语法发生了很大改变,并更名为C++/CLI。查看此链接获取详细信息。
  4. 是的
  5. 只要调用托管DLL,CLR就会被使用。

将现有的Win32 C++库重新编译成C++/CLI,这样做是否现实? - ng5000
2
其实不然...... C++/CLI 是一门不同的语言,打开 CLR 的 C++ 也是不同的。如果你想在 Visual C++ 项目中打开 CLR 并实现这个目标,是可以做到的,但在编译过程中可能会出现问题。这将取决于特定库的实现。 - Aamir
抱歉如果这是一个愚蠢的问题,但是“C++/CLI”和“打开CLR的C++”之间有什么区别? - ng5000
1
“打开CLR的C++”是指可以通过属性将CLR打开的任何C++项目。您可以为一个文件、多个文件或整个项目打开CLR。像这样创建的项目称为C++/CLI项目。在VS2005中,新建项目->VisualC++->CLR->新建项目。默认情况下,它已经打开了/CLR开关,您可以直接在其中编写C++/CLI代码,无需进行其他操作。 - Aamir

2
请注意,您还可以对C#dll进行IL往返并导出静态方法,其基本与C ++ / CLI中的导出相同。但是,这始终是一个编译后步骤,并且它确实具有一些注意事项(顺便说一下,您的C ++ / CLI导出也有这些注意事项)。您可以使用ILDASM查看C#和C ++ / CLI DLL的导出方式;它类似于以下示例(来自网络上的一个样本):
// unmexports.il
// Compile with : ilasm unmexports.il /dll
assembly extern mscorlib {}
..assembly UnmExports {}
..module UnmExports.dll
// This flag is important
..corflags 0x00000002
// This instructs the CLR to create a marshaling thunk for the unmanaged caller
..vtfixup [1] int32 fromunmanaged at VT_01
..data VT_01 = int32(0)
..method public static void foo()
{
..vtentry 1:1
..export [1] as foo
ldstr "Hello from managed world"
call void [mscorlib]System.Console::WriteLine(string)
ret
}

1

使用 ilasm 2.0,您需要的代码更少,因为它可以自动生成大部分的冗余代码。现在只有 .export 指令是真正需要的。

// unmexports.il
// Compile with : ilasm unmexports.il /dll
.assembly extern mscorlib { auto }
.assembly UnmExports {}
.module UnmExports.dll
.method public static void foo()
{
  .export [1] as foo
  ldstr "Hello from managed world"
  call void [mscorlib]System.Console::WriteLine(string)
  ret
}

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