【问题标题】:Invoking a C function dynamically at runtime without knowing its prototype在运行时动态调用 C 函数而不知道其原型
【发布时间】:2013-04-27 14:34:51
【问题描述】:

我想知道是否可以实现上述目标。显然,可以在 Linux 中使用dlopen, dlsym 方法加载库并调用它的方法。但它需要知道函数原型才能在调用之前将void * 指针转换为相应的类型。

假设原型元数据可以在外部提供(使用一些描述符文件等)

有没有办法做到这一点?

【问题讨论】:

  • 我相信这通常是不可能的(尽管使用可变参数的一些黑客可能会起作用)。你有一个特定的目的吗?
  • C 不是像 python 或 javascritp 这样的动态语言,你必须知道你的函数原型
  • @larsmans 实际上,这是针对一些实验性代码,我正在尝试为 RPC 服务器编写类似功能,其中通过 HTTP 调用获得的参数将用于调用库中存在的某些函数可以在运行时加载。

标签: c linux shared-libraries ld


【解决方案1】:

这是可能的,但不要指望任何可移植的东西。例如,您可以使用臭名昭著的libffi 库。伪 C 中的虚拟示例:

// We make some kind of descriptor structure and possible return and argument types
enum c_type {
    C_TYPE_CHAR,
    C_TYPE_INT,
    C_TYPE_FLOAT,
    C_TYPE_PTR,
    C_TYPE_VOID
};

struct func_proto_desc {
    enum c_type ret_type;
    int n_args; // Reasonable convention: -1 for variadic
    c_type *arg_types;
};

// Imaginary function that parses textual metadata and returns a function descriptor
void parse_func_desc(const char *str, struct func_proto_desc *desc);

// this is how to use it:
struct func_proto_desc fproto;
parse_func_desc("void (*)(int, float, const char *)", &fproto);

ffi_cif cif;
ffi_type *args[3];
void *vals[3];

int n = 42;
float f = 3.1415927;
const char *s = "Hello world!";

vals[0] = &n;
vals[1] = &f;
vals[2] = &s;

// Here you can set up the types according to the type description
// that the parser function returned
// (this one is an imaginary function too)
populate_ffi_types_from_desc(args, &fproto);

// Use libffi to call the function
ffi_prep_cif(&cif, FFI_DEFAULT_ABI, fproto->n_args, &ffi_type_void, args);
ffi_call(&cif, func_ptr, NULL, vals);

这样的事情应该可以帮助您入门。

【讨论】:

  • 这似乎可行。接受这个作为正确答案,因为我没有看到这种方法的任何绊脚石。会试试这个看看。但只是好奇这个库是如何实现它自己的语言不支持的一些东西的。
  • @chamibuddhika 它使用了沉重而邪恶的组装黑客:)
猜你喜欢
  • 2020-11-02
  • 2012-03-09
  • 1970-01-01
  • 2020-09-24
  • 1970-01-01
  • 2013-06-12
  • 2016-07-18
  • 1970-01-01
  • 2020-09-05
相关资源
最近更新 更多