【问题标题】:How to call method on a pointer to a C++ object using OpCodes.Calli如何使用 OpCodes.Calli 在指向 C++ 对象的指针上调用方法
【发布时间】:2013-12-08 17:50:57
【问题描述】:

当使用 .calli IL 指令从 .NET 调用 C++ 对象的方法时,如何解析指向要调用的实际方法的指针?我意识到这将取决于平台。

我知道优秀的 SharpDX 库广泛使用 .calli 指令,并且我已经查看了它生成的代码,方法指针被拉出来是这样的:

((void**)(*(void**)_nativePointer))[69]

其中 _nativePointer 是指向对象实例的指针。然后将其转换为取消引用的 void**,然后再次转换为索引到插槽 69 的 void**。我只是无法弄清楚这里到底发生了什么。

【问题讨论】:

  • SharpDX 并不是一个很好的例子,它会调用 DirectX。它使用 COM 接口,您可能会看到它从 v-table 中挖掘出函数指针。了解 COM 的工作原理远远超出了 SO 答案的范围。很多关于它的书。

标签: c# c++ .net il sharpdx


【解决方案1】:

Calli 操作码仅适用于具有vtable 的对象,但不能用于标准 C++ 方法(非虚拟)。它还要求对象遵循相同的ABI,因此这适用于 COM,因为它定义了访问 C++ 对象的标准 ABI。但这不适用于例如 C++ 多重继承。

为了访问对象上的普通 C++ 方法,您需要有一个生成的 C 包装器,它为每个 C++ 方法提供一个普通 C 函数,其中第一个参数通常是 C++ 对象的实例,以下参数是来自 C++ 方法的参数(某些包装器,如 CXXI,有时能够通过遵循编译器 ABI 直接链接到 C++ 对象)。所以为了搭建这座桥,你可以:

  • 开发您自己的 C 包装器(一个动态库 DLL/提供这些函数来转换对 C++ 对象的调用)
  • SWIG 通常用于自动化这种 C++/C# 桥。
  • 还有一些 Mono 人尝试提供名为 CXXI 的 C++ 桥接,但似乎尚未开发。

【讨论】:

  • 尽管这不是我想要的答案,但这是正确的答案 =(。谢谢!
  • 如何使用'calli'来调用普通的C函数?如何获得此地址?这会是通过“LoadLibrary”/“GetProcAddress”吗?
  • calli 允许调用任何本机函数,最后压入 calli 指令的参数是该函数的指针。对于 COM 对象的方法,此指针来自与此方法关联的 vtable 槽。对于导出的 DLL 函数,这确实是 LoadLibrary/GetProcessAddress
猜你喜欢
  • 2012-07-15
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多