【问题标题】:C++ How to find class by it's name?C ++如何通过名称查找类?
【发布时间】:2017-10-05 12:46:56
【问题描述】:

如何通过知道类名和方法名找到一个类来调用它的方法?

详情: 我正在尝试编写库来替换另一个程序中的一些函数,该程序也是由 LD_PRELOAD 功能使用 C++ 编写的。 我需要能够从要集成此库的程序中调用函数。

【问题讨论】:

  • 确实知道符号一旦通过编译器就会是mangled?这意味着一个成员函数,例如SomeClass::someFunction 不会这么简单吧? C++ 规范没有指定重整方案,它取决于编译器及其实现。您需要知道要访问的函数的错位名称。
  • 此外,C++ 没有 type introspection 并且不可能获得“只是”一个类。您需要告诉系统获取指向某个类的特定成员函数的指针,使用重整的名称。
  • 此外,请记住,非静态成员函数需要调用对象。这通常作为隐藏的第一个参数传递给成员函数,并成为函数中的this 指针。如果覆盖已加载成员函数的函数不处理此特殊参数,则您的代码将永远无法工作。
  • 错位名称看起来像 _ZNK4GNET5Skill8GetLevelEv 吗?我在 IDA PRO 中找到了这个名字。我可以找到并调用只知道这种类型名称的函数吗?或者也许我需要找到这个函数所在的地址以便在运行时调用它?如果我没有主程序的来源(我可以通过 IDA 打开它),我需要知道如何调用这些方法的所有可能方式。谢谢。
  • 是的,这是一个典型的错误名称。如果你知道这个名字,你就可以获得函数的句柄并调用它。 然而如果它是非静态成员函数,那么(正如我之前所说)它需要一个对象来调用。如果您没有正确类的对象,而这实际上是不可能从库或可执行文件中获取的,那么您根本无法在没有未定义行为的情况下调用它。如果你有定义类的头文件,那么你可以使用该类定义来创建一个对象。

标签: c++ linux ld-preload


【解决方案1】:

C++ 在编译过程中会丢失所有的类命名信息!

你不能这样做:

Class.forName("MyClass");

就像你从 Java 中知道的那样。

http://en.cppreference.com/w/cpp/language/class

这种技术被称为反射,它不被 C++ 支持 您可以使用框架(例如 Boost)来帮助您,但您要调用的方法必须使用此框架声明和定义。

【讨论】:

  • 我可以使用这样的函数名称:_ZNK4GNET5Skill8GetLevelEv 从我的库中调用它们吗?
  • 你将如何处理类初始化器?并将隐式this 传递给每个方法?我担心你在这里给自己设置了一份非常讨厌的工作:/
  • @LemanRass 永远不要这样做,C++ 不支持反射,无论如何尝试都是一个非常糟糕的主意。这是高度依赖编译器的,并且可能不会在任何其他环境中工作。如果外部库没有让你访问该方法,你不应该使用它!
【解决方案2】:

C++ 不支持反射,因此您无法在编译后按名称搜索函数/类。

听起来如果可能的话,设计需要重新设计。理想情况下,您应该更新库以包含程序所需的内容。要么将程序中的通用逻辑提取到第三个库中,要么将程序需要调用的函数放入当前库中,然后将要操作的相关数据传递到库中。

如果这不可能,您可以将程序中的函数指针传递到您的库中 - 这允许库访问它需要的函数,而无需真正了解它的来源。

void library_function1(std::function<void(int)> func)
{
     func(1);
}

【讨论】:

    猜你喜欢
    • 2018-10-10
    • 2012-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 2018-10-01
    • 2015-06-23
    • 2016-01-15
    • 1970-01-01
    相关资源
    最近更新 更多