0

I have an array of structs, where the .act values are not strings, but function names:

cgi_object_t cgi_machine_learning_handlers[] =
{
{
    .path = "schema",
    .grp = ACC_GRP_ML,  
    .r_vdom = VDOM_PER_VDOM,
    .r_global = VDOM_PER_VDOM,
    .act = cgi_ml_schema,
    .flags = API_FLAG_NO_SCHEMA, 
},
{
    .path = "policy.svmattacktypes",
    .grp = ACC_GRP_ML,  
    .r_vdom = VDOM_PER_VDOM,
    .r_global = VDOM_PER_VDOM,
    .act = cgi_ml_policy_svmattacktypes_get,
    .flags = API_FLAG_NO_SCHEMA, 
}

I'm trying to access these function names -- cgi_ml_schema and such, as strings. Is there a way to do this? I tried using # below but it's complaining that there are stray '#'s in the program.

const char * var = json_object_object_get(request, #(m->act))
response = json_object_object_get(info, #(m->act));
3
  • 2
    Add the name as a field in the struct. Commented Apr 2, 2021 at 18:57
  • True. Is there an alternative where I don't have to do that? Reading the pointer names directly? @dbush Commented Apr 2, 2021 at 19:00
  • You might have to create an X macro to do add some kind of introspection here in a maintainable way. However, this would only work if you never change the function pointers after initializing them. Commented Apr 2, 2021 at 19:29

1 Answer 1

1

You are basically asking if you can read the name of a pointer from the pointer itself. Lets try it. Can you tell me what is the name of the function at address 0x55c0c6e93190? I guess no. Nor can anyone, unless the corresponding name is stored in memory somewhere. After compilation the name of variables is no more (unless you plan of leveraging Debug information).

But you can try to automate the storing of the name along with the pointer like this:

#include <stdio.h>

typedef int (*fnptr_t)(int a, int b);

typedef struct named_ptr {
    fnptr_t ptr;
    const char *name;
} named_ptr;

named_ptr make_named_ptr(fnptr_t ptr, const char *name) {
    named_ptr p = {ptr, name};
    return p;
}
#define MAKE_NAMED_PTR(x) make_named_ptr(x, #x)

typedef struct cgi_object_t {
    char *path;
    int grp, r_vdom, r_global;
    named_ptr act;
    int flags; 
} cgi_object_t;

enum dummy {ACC_GRP_ML, VDOM_PER_VDOM, API_FLAG_NO_SCHEMA};
int cgi_ml_schema(int a, int b) { return 0; }
int cgi_ml_policy_svmattacktypes_get(int a, int b) { return 0; }

int main(void) 
{
    cgi_object_t cgi_machine_learning_handlers[] = {
        {
            .path = "schema",
            .grp = ACC_GRP_ML,  
            .r_vdom = VDOM_PER_VDOM,
            .r_global = VDOM_PER_VDOM,
            .act = MAKE_NAMED_PTR(cgi_ml_schema),
            .flags = API_FLAG_NO_SCHEMA, 
        },
        {
            .path = "policy.svmattacktypes",
            .grp = ACC_GRP_ML,  
            .r_vdom = VDOM_PER_VDOM,
            .r_global = VDOM_PER_VDOM,
            .act = MAKE_NAMED_PTR(cgi_ml_policy_svmattacktypes_get),
            .flags = API_FLAG_NO_SCHEMA, 
        }
    };
    
    for (size_t i = 0; i < 2; ++i) {
        cgi_object_t *m = cgi_machine_learning_handlers + i;
        printf("%s is at address %p\n", m->act.name, m->act.ptr);
    }
    
    return 0;
}

I really guessed and made up a lot of stuff, but the idea is there. Next time, you should provide a Minimal, Reproducible Example.

Test it here.

If your compiler supports them, the function call can be replaced by compound literals.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.