在运行时动态调用C函数而不知道其原型

在运行时动态调用C函数而不知道其原型,c,linux,shared-libraries,ld,C,Linux,Shared Libraries,Ld,我想知道是否有可能实现上述目标。显然,在Linux中可以使用dlopen、dlsym方法加载库并调用库的方法。但在调用之前,需要知道函数原型才能将void*指针转换为相应的类型 假设可以从外部提供原型元数据(使用一些描述符文件等) 有办法做到这一点吗?当然有可能,但不要期望任何便携设备。例如,您可以使用臭名昭著的库。伪C中的虚拟示例: // We make some kind of descriptor structure and possible return and argument typ

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

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


有办法做到这一点吗?

当然有可能,但不要期望任何便携设备。例如,您可以使用臭名昭著的库。伪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);

像这样的东西应该可以让你开始了。

这当然是可能的,但不要期望任何便携的东西。例如,您可以使用臭名昭著的库。伪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);

像这样的东西应该可以让你开始了。

我相信这在一般情况下是不可能的(尽管使用varargs的一些黑客可能会奏效)。你有什么特别的目的吗?C不是像python或JavaScriptp那样的动态语言,你必须知道你的电脑的原型function@larsmans事实上,这是为一些实验性代码编写的,我正试图为类似RPC服务器的功能编写这些代码,在这些功能中,通过HTTP调用获得的参数将用于调用库中的某些函数,这些函数可以在运行时加载。我相信,这在一般情况下是不可能的(尽管使用varargs的一些黑客可能会奏效)C不是像python或JavaScriptp那样的动态语言,你必须知道你的语言的原型function@larsmans事实上,这是一些实验性代码,我正试图为类似RPC服务器的功能编写这些代码,其中通过HTTP调用获得的参数将用于调用中存在的某些函数一个可以在运行时加载的库。这似乎是可行的。接受这一点作为正确答案,因为我看不到这种方法的任何障碍。我将尝试一下,看看。但只是好奇这个库如何实现一些它自己的语言不支持的东西。@chamibuddhika它使用了严重而邪恶的汇编黑客:)这似乎是可行的。接受这一正确答案,因为我认为这种方法没有任何障碍。我会试试看。但我只是好奇这个库是如何实现一些它自己的语言所不支持的东西的。@chamibuddhika它使用了严重而邪恶的汇编黑客:)