Code_Complete
Code_Complete

Reputation: 115

How to obtain the function name and number of arguments from a function in C?

Lets say I am maintaining an array of function structures in which I store API information.

This is definition of function structure:

typedef struct function {
    void (*func)(long, ...);
    char* name;
    int argc;
    char *argv[];
} function;

function api_list[N]

I would maintain a list of such structures. Now given any function, I want to write a function Register(api_list, fp) which adds one such structure initialized with details of function fp.

int fp(int a, int b) {
    return a+b;
}

Register(api_list, fp);

How to do it in C?

Upvotes: 2

Views: 128

Answers (2)

Zan Lynx
Zan Lynx

Reputation: 54325

I believe you will need to either parse the C function declarations yourself or find some other code to do it. I looked around a bit and there's code for this in the Ruby FFI, PerlXS and other script binding generators like SWIG. I also saw the XML plugin to GCC which generates XML describing the program.

If you look up C's BNF or EBNF definitions and know a bit of parsing theory, figuring out C functions is not hard. C++ is a whole other ball o' wax.

Note: I think I misunderstood. The following is for calling C functions with unknown number and types of arguments. Not for finding out what the function signature already looks like.

Look at the FFI (Foreign Function Interface) library which can be found at Sourceware: https://sourceware.org/libffi/

This is packaged with many Linux systems already because it is heavily used by interpreted languages that need to call C functions.

Upvotes: 1

Grzegorz Szpetkowski
Grzegorz Szpetkowski

Reputation: 37914

Now given any function, I want to write a function Register(api_list, fp) which adds one such structure initialized with details of function fp.

There is no way to do this in Standard C. The main reason is you need keep track of original definition of an function to call it via such structure. You actually could store every function pointer as struct member:

void (*func)()

that is fine, but any attempt to call such function when type is not compatible (both parameters and return type are not the same) with original definition will invoke undefined behaviour. This means, that you would need to cast it properly for every call:

((int (*)(int, int)) api_list[0])(1, 2);

You may use GCC extensions typeof, but this method requires writing function's name (here fp) explicitely:

int result = ( (typeof(fp)*) api_list[0].func)(1, 2);

Even if you have stored somehow character string "fp" inside name member, there is no way to "connect" it with typeof, since it does not take string literals (well it takes, but not in the way you want) and in general there is no way to have it "destringized" as fp token.

Here is an illustration of above concepts:

#include <stdio.h>

typedef void (*GENERIC_FUNC_PTR)();

typedef struct function
{
    GENERIC_FUNC_PTR func;
} function;

void Register(function *api_list, GENERIC_FUNC_PTR func)
{
    api_list->func = func;
}

int add(int a, int b)
{
    return a + b;
}

void print_message(void)
{
    printf("%s\n", __func__); 
}

int main(void)
{
    function api_list[10];
    Register(api_list, (GENERIC_FUNC_PTR) add);
    Register(api_list + 1, (GENERIC_FUNC_PTR) print_message);

    printf("%d\n", ( (typeof(add)*) api_list[0].func)(1, 2));
    ( (typeof(print_message)*) api_list[1].func)();

    return 0;
}

Upvotes: 0

Related Questions