Thread: function pointer modularization

  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    43

    function pointer modularization

    I'm trying to modularize at compile time by doing something like the following:

    REGISTER_MODULE("module_name");

    int module_name()
    {
    ...
    }

    I thought this might be able to be done through function pointers like the following:

    typedef struct a
    {
    void (*do_nothing)(char *);
    } b;

    But I don't really know where or how to call this outside of main() or another function.

    Thanks,
    matth

  2. #2
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,981
    Let's start with using function pointers and go from there. Post back with additional, specific questions if you get stuck.

    http://www.newty.de/fpt/index.html

    gg

  3. #3
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by Codeplug View Post
    Let's start with using function pointers and go from there. Post back with additional, specific questions if you get stuck.

    http://www.newty.de/fpt/index.html

    gg
    Got function pointers down already but to sum this up, I need to know how to call a function in the global scope.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You can't do anything at global scope. When your program starts, main starts; when main stops, your program stops. Your functions can and will be defined at global scope, so that they can be called from whatever function has control.

  5. #5
    Ex scientia vera
    Join Date
    Sep 2007
    Posts
    477
    You could perhaps do whatever you want to do with a constructur - those are called before main, but I doubt your program will be compiled without main.

  6. #6
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by tabstop View Post
    You can't do anything at global scope. When your program starts, main starts; when main stops, your program stops. Your functions can and will be defined at global scope, so that they can be called from whatever function has control.
    Well, more specifically heres and example i found. In the PHP source I'm pretty sure theres function pointers inside these struct's. I'm trying to do something like this

    PHP_FUNCTION(hello_world);

    and

    static function_entry hello_functions[] = {
    PHP_FE(hello_world, NULL)
    PHP_FE(hello_long, NULL)
    PHP_FE(hello_double, NULL)
    PHP_FE(hello_bool, NULL)
    PHP_FE(hello_null, NULL)
    {NULL, NULL, NULL}
    };


    which are done at the global scope of the extension.

    I took this from: http://devzone.zend.com/node/view/id/1021

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by mingerso View Post
    Well, more specifically heres and example i found. In the PHP source I'm pretty sure theres function pointers inside these struct's. I'm trying to do something like this

    PHP_FUNCTION(hello_world);

    and
    Code:
    static function_entry hello_functions[] = {
        PHP_FE(hello_world, NULL)
        PHP_FE(hello_long, NULL)
        PHP_FE(hello_double, NULL)
        PHP_FE(hello_bool, NULL)
        PHP_FE(hello_null, NULL)
        {NULL, NULL, NULL}
    };
    which are done at the global scope of the extension.

    I took this from: http://devzone.zend.com/node/view/id/1021
    Most of those are just definitions, and definitions can and should go in global scope (if it's outside main, it's in global scope). Since PHP is a scripting language, everything (from its point of view) is in a main() already. Note: that was an extreme generalization and is wrong, but you should get the idea -- you don't have to tell PHP where to start, it just starts at the top of the file and goes. C does not. You'll have to decide whether you are calling this from PHP or from C.

  8. #8
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by mingerso View Post
    Well, more specifically heres and example i found. In the PHP source I'm pretty sure theres function pointers inside these struct's. I'm trying to do something like this

    PHP_FUNCTION(hello_world);

    and

    static function_entry hello_functions[] = {
    PHP_FE(hello_world, NULL)
    PHP_FE(hello_long, NULL)
    PHP_FE(hello_double, NULL)
    PHP_FE(hello_bool, NULL)
    PHP_FE(hello_null, NULL)
    {NULL, NULL, NULL}
    };


    which are done at the global scope of the extension.

    I took this from: http://devzone.zend.com/node/view/id/1021
    To add to this, I just went through the PHP source and found:

    main/php3_compat.h:#define function_entry zend_function_entry

    and in Zend/zend_API.h
    typedef struct _zend_function_entry {
    char *fname;
    void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
    struct _zend_arg_info *arg_info;
    zend_uint num_args;
    zend_uint flags;
    } zend_function_entry;


    and also called from PHP_FE which is pointed to ZEND_FE which points to ZEND_FENTRY:

    Zend/zend_API.h:#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },

    but I still don't get it..

  9. #9
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by tabstop View Post
    Most of those are just definitions, and definitions can and should go in global scope (if it's outside main, it's in global scope). Since PHP is a scripting language, everything (from its point of view) is in a main() already. Note: that was an extreme generalization and is wrong, but you should get the idea -- you don't have to tell PHP where to start, it just starts at the top of the file and goes. C does not. You'll have to decide whether you are calling this from PHP or from C.
    Sorry, but I understand all of this. Basically I'm trying to write modules that can be defined on a global scope at compile time. This in case will register a pointer to the function and a name in a global structure or something like that. I'm sure I'm just missing something, but if you can tell me how to do that, great...

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by mingerso View Post
    To add to this, I just went through the PHP source and found:

    main/php3_compat.h:#define function_entry zend_function_entry

    and in Zend/zend_API.h
    typedef struct _zend_function_entry {
    char *fname;
    void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
    struct _zend_arg_info *arg_info;
    zend_uint num_args;
    zend_uint flags;
    } zend_function_entry;


    and also called from PHP_FE which is pointed to ZEND_FE which points to ZEND_FENTRY:
    Code:
    Zend/zend_API.h:#define ZEND_FENTRY(zend_name, name, arg_info, flags)	{ #zend_name, name, arg_info, (zend_uint) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
    but I still don't get it..
    I'm turning this over to my Hat of Guessing, since I'm not sure still what you don't understand. The reason for the struct is that to have an array of function pointers, they must all have the same signature; so all the stuff about handler and _zend_arg_info is how these people have decided to handle the argument lists. ZEND_FENTRY appears to be a way to get that data into an initializer list, since the # turns the function name into a string literal, and the rest of it matches the fields of the struct. So that's what happening with PHP_FE -- it's initializing the array of structs.

    You'll notice that we still have to accumulate them ourselves into the one place -- all the function names were given explicitly in that array declaration. If you want to do a lot of REGISTER_FUNCTIONS(), you can probably do that too with an extra pre-processor or so, but my medicine-addled head is not telling me how right this minute.

  11. #11
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by tabstop View Post
    I'm turning this over to my Hat of Guessing, since I'm not sure still what you don't understand. The reason for the struct is that to have an array of function pointers, they must all have the same signature; so all the stuff about handler and _zend_arg_info is how these people have decided to handle the argument lists. ZEND_FENTRY appears to be a way to get that data into an initializer list, since the # turns the function name into a string literal, and the rest of it matches the fields of the struct. So that's what happening with PHP_FE -- it's initializing the array of structs.

    You'll notice that we still have to accumulate them ourselves into the one place -- all the function names were given explicitly in that array declaration. If you want to do a lot of REGISTER_FUNCTIONS(), you can probably do that too with an extra pre-processor or so, but my medicine-addled head is not telling me how right this minute.
    I'm not sure if what you just said is all correct but we seem to be on the same page now. So obviously the ZEND_FENTRY lines up to the struct. Ok, lets say I just wanted to do something like this that doesn't actually work:

    void add_module(char * mname, void (*mp)(void));

    #define ADD_MODULE(mname, mpointer) add_module(mname, mpointer)

    typedef struct
    {
    void (*add)(char *,void(*mp)(void));
    } add_module;

    static add_module nm[] = {
    ADD_MODULE("module_name", module_function);
    };

    I'm probably just being slow today but if you have any examples that relate to this and the PHP one it would make me _very_ happy.

  12. #12
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by mingerso View Post
    I'm not sure if what you just said is all correct but we seem to be on the same page now. So obviously the ZEND_FENTRY lines up to the struct. Ok, lets say I just wanted to do something like this that doesn't actually work:

    void add_module(char * mname, void (*mp)(void));

    #define ADD_MODULE(mname, mpointer) add_module(mname, mpointer)

    typedef struct
    {
    void (*add)(char *,void(*mp)(void));
    } add_module;

    static add_module nm[] = {
    ADD_MODULE("module_name", module_function);
    };

    I'm probably just being slow today but if you have any examples that relate to this and the PHP one it would make me _very_ happy.
    Obviously, everything can't be called add_module -- but the other bad side of this is I think you think there's something dynamic going on here. But there isn't: all we're doing is initializing an array. An example I haven't tested, so even though I'm being easy on myself there's going to be four errors in it:
    Code:
    void hello_world(void *dummy_arg) {
        printf("Hello world!\n");
    }
    
    void read_int(void *int_var) {
        printf("I need an integer: ");
        scanf("%d", int_var);
    }
    
    void print_linked_list(void *head) {
        Node *item = head;
        while (item != NULL) {
            printf("%d\n", item->data);
            item = item->next;
        }
    }
    
    struct fn_entry {
        char *fn_name;
        void (*fn_ptr)(void *);
    }
    
    #define FUNCTION(x) { #x, x }
    
    struct fn_entry function_list[] = {
        FUNCTION(hello_world),
        FUNCTION(read_int),
        FUNCTION(print_linked_list)
    };
    In my example, each of my functions knows what to do with the info it has (which is a simple pointer in each case), so I didn't need the handler part -- if some of your functions needed two ints, or three ints and a double, or whatever, you'd need that to turn the function list you provide into a void * to go into the actual function itself.

    The FUNCTION is just a macro: so FUNCTION(hello_world) is replaced by the preprocessor with { "hello_world", hello_world } -- a char * (actually a const char *) and a function pointer, which means it initializes one struct in my array of structs.

  13. #13
    Registered User
    Join Date
    Mar 2008
    Posts
    43
    Quote Originally Posted by tabstop View Post
    Obviously, everything can't be called add_module -- but the other bad side of this is I think you think there's something dynamic going on here. But there isn't: all we're doing is initializing an array. An example I haven't tested, so even though I'm being easy on myself there's going to be four errors in it:
    Code:
    void hello_world(void *dummy_arg) {
        printf("Hello world!\n");
    }
    
    void read_int(void *int_var) {
        printf("I need an integer: ");
        scanf("%d", int_var);
    }
    
    void print_linked_list(void *head) {
        Node *item = head;
        while (item != NULL) {
            printf("%d\n", item->data);
            item = item->next;
        }
    }
    
    struct fn_entry {
        char *fn_name;
        void (*fn_ptr)(void *);
    }
    
    #define FUNCTION(x) { #x, x }
    
    struct fn_entry function_list[] = {
        FUNCTION(hello_world),
        FUNCTION(read_int),
        FUNCTION(print_linked_list)
    };
    In my example, each of my functions knows what to do with the info it has (which is a simple pointer in each case), so I didn't need the handler part -- if some of your functions needed two ints, or three ints and a double, or whatever, you'd need that to turn the function list you provide into a void * to go into the actual function itself.

    The FUNCTION is just a macro: so FUNCTION(hello_world) is replaced by the preprocessor with { "hello_world", hello_world } -- a char * (actually a const char *) and a function pointer, which means it initializes one struct in my array of structs.
    Thanks for the example and here is a modified simpler/working example:
    Code:
    #include <stdio.h>
    
    void hello_world(void)
    {
        printf("Hello world!\n");
    }
    
    struct fn_entry
    {
        char *fn_name;
        void (*fn_ptr)(void);
    };
    
    #define FUNCTION(x) { #x, x }
    
    struct fn_entry function_list[] =
    {
        FUNCTION(hello_world)
    };
    
    int main()
    {
            printf("test_name: %s\n", function_list[0].fn_name);
            printf("test_pointer: ");
            function_list[0].fn_ptr();
    
            return 0;
    }
    This almost answers my question, but I'll have to get back to that later.

  14. #14
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    And if we need to have a master header file with those initializers would it be valid to do something like:
    Code:
    ...
    #ifndef FUNC_VECTOR
    #  define FUNC_VECTOR
        struct fn_entry function_list[] = { ... };
    #  define FUNC_VECTOR_LENGTH ( sizeof(function_list)/sizeof(struct fn_entry) )
    #else
        extern struct fn_entry *function_list;
    #endif
    Just an idea...
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

  15. #15
    uint64_t...think positive xuftugulus's Avatar
    Join Date
    Feb 2008
    Location
    Pacem
    Posts
    355
    That was not exactly clear thinking... It appears you can not have declaration guards at compile time, or i don't know how to do it. I put up a small test with three files, and the struct array was included in both .o files with my "silly" approach.
    Code:
    ...
        goto johny_walker_red_label;
    johny_walker_blue_label: exit(-149$);
    johny_walker_red_label : exit( -22$);
    A typical example of ...cheap programming practices.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  3. Function Pointer help
    By Skydt in forum C Programming
    Replies: 5
    Last Post: 12-02-2005, 09:13 AM
  4. pointers
    By InvariantLoop in forum C Programming
    Replies: 13
    Last Post: 02-04-2005, 09:32 AM
  5. Interface Question
    By smog890 in forum C Programming
    Replies: 11
    Last Post: 06-03-2002, 05:06 PM