If I have this setup:
#include <stdlib.h>
#define NEW_FOO ((foo_t*)malloc(sizeof(foo_t)))
void foo_func(void);
typedef struct {
void (*foo) (void);
} foo_t;
int main(void) {
foo_t *a = NEW_FOO;
foo_t *b = NEW_FOO;
a->foo = foo_func;
b->foo = foo_func;
a->foo();
b->foo();
}
void foo_func(void) {
// determine wheter a or b was called?
}
Can I then find out, wheter a or b was the caller of foo_func, strictly without a parameter like self, this, ...?
The return address should be on the stack, so you should be able to identify the caller somehow, no?
I thought of a possible approach (it builds upon the idea above): The first time the foo_func is called (maybe through an initialization function, but let's leave that out to keep it simple) through a->foo(), store the address of struct a in some sort of array of pointers, I would assume. Same with b->foo(). Then, anytime that a->foo() or b->foo() is called, you would compare the address of the caller struct with the contents in the array to identify wheter it was a or b that called foo_func().
It's just that I have no Idea if and/or how that is possible, so if anyone of you could help me with this, I would be very glad!
I guess you're annoyed about the unsightliness of constructions like:
a->foo (a, arg0, arg1);
b->bar (b, arg0);
Unfortunately, the style of programming you've adopted does force this style on you, if you want to implement a simulation of polymorphic methods. Maybe you can implement a set of macros so you can write something like:
METHOD_CALL2 (foo, a, arg0, arg1);
METHOD_CALL1 (bar, b, arg0);
and so not have to repeat the "object" names a, b, etc., in the call. I've seen this done as well but, in my view, it doesn't look any prettier, and I'm sure it's no more maintainable.
As this is C, not C++, in the end you're going to have to have some way to pass your equivalent of this to the "methods" in your implementation. You might be able to disguise it with macros and variable-length argument lists, but it's going to have to happen somehow.
But why worry? This is idiomatic C code -- every application and library that takes an object-oriented approach to C will be using constructions of the form you want to avoid. People will understand what you're doing. Trying to disguise it will not make your code easier to follow, I suspect.
Related
I’m building a small multi-platform C library. A design objective is to have a set of header files that are suitably generic, and which define a number of placeholder pointers to structs - if that’s the right term - like this:
/* mylib_types.h */
typedef struct _mylib_matrix *mylib_matrix;
These placeholders can be used to specify the parameters to the function prototypes in the other headers, like:
/* mylib_api.h */
MY_API mylib_status mylibAddMatrix(mylib_matrix a,
mylib_matrix b,
mylib_matrix* result);
So, that’s fine for the headers - everything is self-contained and stand-alone. Then, when it comes to implementing the library I want to use different underlying, platform specific, libraries to actually implement the methods.
The idea being that the library is optimised for any given platform, but the API to the library will be universally defined (so easily cross-compiled).
The problem I have is that: yes - I have got this working - but in the rather crude way using casting. I just wonder what the best practice - if any - actually is?
For example, in my implementation of a method I must then remember to immediately cast the placeholder pointer to the actual type of thing we are using for that platforms implementation, and similarly cast back any results.
e.g.
/* mylib_matrix.c */
#include “mylib_types.h"
#include “mylib_api.h”
#include <PlatformSpecificFunkyMatrix.h>
MY_API mylib_status mylibAddMatrix(mylib_matrix a,
mylib_matrix b,
mylib_matrix* result)
{
*result = (mylib_matrix)PlatformSpecificFunkyMatrix_AddMatrix(
(PlatformSpecificFunkyMatrix*)a,
(PlatformSpecificFunkyMatrix*)b);
return MYLIB_SUCCESS;
}
This all seems very brittle and liable for me to forget a cast or allowing the compiler to do any type checking. Is it at all principled?
I guess I could be explicit in my types of cast - but that still requires some consideration. Perhaps some pre-processor #defines might help wrap things up, but of course that can get rather messy... I could of course go and redefine the low-level structs (e.g. mylib_matrix) for each implementation, but then we are talking a different set of headers for each platform (again, I could go with the preprocessor to help swap the right definitions in or out).
Hmmm. Maybe I’m dwelling too much upon this...
One way to get around the casting.
In the platform specific file, use:
struct _mylib_matrix
{
PlatformSpecificFunkyMatrix* realMatrix;
};
and
MY_API mylib_status mylibAddMatrix(mylib_matrix a,
mylib_matrix b,
mylib_matix* result)
{
PlatformSpecificFunkyMatrix* r =
PlatformSpecificFunkyMatrix_AddMatrix(a->realMatrix, b->realMatrix);
*result = malloc(sizeof(_mylib_matrix));
*result->realMatrix = r
return MYLIB_SUCCESS;
}
Better still...
You can avoid the double indirection and the need for casting by using:
struct _mylib_matrix
{
// Add all the data here that you have in PlatformSpecificFunkyMatrix
};
typedef struct _mylib_matrix PlatformSpecificFunkyMatrix;
and then,
MY_API mylib_status mylibAddMatrix(mylib_matrix a,
mylib_matrix b,
mylib_matix* result)
{
*result = PlatformSpecificFunkyMatrix_AddMatrix(a, b);
return MYLIB_SUCCESS;
}
Is there a "proper" way to implement higher order functions in C.
I'm mostly curious about things like portability and syntax correctness here and if there are more than one ways what the merits and flaws are.
Edit:
The reason I want to know how to create higher order functions are that I have written a system to convert PyObject lists (which you get when calling python scripts) into a list of C structures containing the same data but organized in a way not dependant on the python.h libraries. So my plan is to have a function which iterates through a pythonic list and calls a function on each item in the list and places the result in a list which it then returns.
So this is basically my plan:
typedef gpointer (converter_func_type)(PyObject *)
gpointer converter_function(PyObject *obj)
{
// do som stuff and return a struct cast into a gpointer (which is a void *)
}
GList *pylist_to_clist(PyObject *obj, converter_func_type f)
{
GList *some_glist;
for each item in obj
{
some_glist = g_list_append(some_glist, f(item));
}
return some_glist;
}
void some_function_that_executes_a_python_script(void)
{
PyObject *result = python stuff that returns a list;
GList *clist = pylist_to_clist(result, converter_function);
}
And to clearify the question: I want to know how to do this in safer and more correct C. I would really like to keep the higher order function style but if that is frowned upon I greatly appreciate ways to do this some other way.
Technically, higher-order functions are just functions that take or return functions. So things like qsort are already higher-order.
If you mean something more like the lambda functions found in functional languages (which is where higher order functions really become useful), those are quite a bit harder and can't be done naturally in current standard C. They're just not part of the language. Apple's blocks extension is the best candidate. It only works in GCC (and LLVM's C compiler), but they are really useful. Hopefully something like that will catch on. Here's a few relevant resources:
Apple's documentation on the feature (references some Apple-specific technologies and also addresses Objective-C, but the core block stuff is part of their extensionto C)
Here's a good intro on blocks
Cocoa for Scientists' overview of C blocks
The big problem with implementing higher-order functions in C is that to do anything non-trivial you need closures, which are function pointers augmented with data structures containing local variables they have access to. Since the whole idea behind closures is to capture local variables and pass those along with the function pointer, it's hard to do without compiler support. And even with compiler support it's hard to do without garbage collection because variables can exist outside of their scope, making it hard to figure out when to free them.
This is an answer to the question: how to compose functions in C, which is redirected here.
You can create a data structure to implement a list data type.
that structure can contain function pointers.
#include<stdlib.h>
#include<malloc.h>
typedef (*fun)();
typedef struct funList { fun car; struct funList *cdr;} *funList;
const funList nil = NULL;
int null(funList fs){ return nil==fs; }
fun car(funList fs)
{
if(!null(fs)) return fs->car;
else
{
fprintf(stderr,"error:can't car(nil) line:%d\n",__LINE__);
exit(1);
}
}
funList cdr(funList ls)
{ if(!null(ls)) return ls->cdr;
else
{
fprintf(stderr,"error:can't cdr(nil) line:%d\n",__LINE__);
exit(1);
}
}
funList cons(fun f, funList fs)
{ funList ls;
ls=(funList) malloc(sizeof(struct funList));
if(NULL==ls)
{
fprintf(stderr,"error:can't alloc mem for cons(...) line:%d\n",__LINE__);
exit(1);
}
ls->car=f;
ls->cdr=fs;
return ls;
}
we can write a function comp which applies a list of functions:
type_2 comp(funList fs, type_1 x)
{
return (null(fs)) ? x : car(fs)(comp(cdr(fs),x));
}
An example of how it works. We use (f g h) as a short notation for cons(f,cons(g,cons(h,nil))), which is applied to a given argument x:
comp((f g h),x)
=
f(comp((g h),x))
=
f(g(comp((h),x)))
=
f(g(h(comp(nil,x))))
=
f(g(h(x)))
if you had used the polymorphic list type in a typed language like SML or Haskell the type of comp should be:
comp :: ([a -> a],a) -> a
because in that context all the members in a list have the same type.
C can be more flexible in this sense. Maybe something like
typedef void (*fun)();
or
typedef (*fun)();
you should see what the C manual say about this. And be sure that all contiguous functions have compatible types.
The functions to compose should be pure, i.e. without side effects nor free variables.
In straight c, this is really only done through function pointers, which are both a pain and not meant for this type of thing (which is partially why they are a pain). Blocks (or closures, according to non-apple) are fantastic for this, though. They compile in gcc-4.x or something, and icc something, but regardless thats what you're looking for. Unfortunately, I can't seem to find any good tutorials online, but suffice to say it works something like this:
void iterate(char *str, int count, (^block)(str *)){
for(int i = 0; i < count; i++){
block(list[i]);
}
}
main() {
char str[20];
iterate(str, 20, ^(char c){
printf("%c ", c);
});
int accum = 0;
iterate(someList, 20, ^(char c){
accum += c;
iterate(str, 20, ^(char c){
printf("%c ", c);
});
});
}
obviously this code is pointless, but it it prints each character of a string (str) with a space in between it, then adds all of the characters together into accum, and every time it does it prints out the list of characters again.
Hope this helps. By the way, blocks are very visible in Mac OS X Snow Leopard api-s, and I believe are in the forthcoming C++0x standard, so they're not really that unusual.
If you're keen on doing this in plain C, you need to remember to include the option to pass in a context pointer from the caller of the functor (the higher-order function) to the function passed in. This lets you simulate enough of a closure that you can make things work easily enough. What that pointer points to... well, that's up to you, but it should be a void* in the functor's API (or one of the many aliases for it, such as gpointer in the GLib world or ClientData in the Tcl C API).
[EDIT]: To use/adapt your example:
typedef gpointer (converter_func_type)(gpointer,PyObject *)
gpointer converter_function(gpointer context_ptr,PyObject *obj)
{
int *number_of_calls_ptr = context_ptr;
*number_of_calls_ptr++;
// do som stuff and return a struct cast into a gpointer (which is a void *)
}
GList *pylist_to_clist(PyObject *obj, converter_func_type f, gpointer context_ptr)
{
GList *some_glist;
for each item in obj
{
some_glist = g_list_append(some_glist, f(context_ptr,item));
}
return some_glist;
}
void some_function_that_executes_a_python_script(void)
{
int number_of_calls = 0;
PyObject *result = python stuff that returns a list;
GList *clist = pylist_to_clist(result, converter_function, &number_of_calls);
// Now number_of_calls has how often converter_function was called...
}
This is a trivial example of how to do it, but it should show you the way.
Practically any interesting higher order function application requires closures, which in C entails the laborous and error-prone routine of manually defining and filling struct function arguments.
It's very difficult to do in straight C. It's more possible in C++ (see functors tutorial or Boost's bind and function libraries). Finally, C++0x adds native support for lambda functions, which takes care for you of capturing in closure all of the variables that your funcion depends on.
If you want to create higher order functions, don't use C. There are C solutions to your problem. They may not be elegant, or they may be more elegant that you realize.
[Edit] I suggested that the only way to achieve this was to use a scripting language. Others have called me out on it. So, I'm replacing that suggestion with this: [/Edit]
What are you trying to achieve? If you want to mimic closures, use a language that supports them (you can tie into Ruby, lua, javascript, etc through libraries). If you want to use callbacks, function pointers are ok. Function pointers combine the most dangerous areas of C (pointers and the weak type system), so be careful. Function pointer declarations are not fun to read, either.
You find some C libraries using function pointers because they have to. If you're writing a library, maybe you need to use them, too. If you're just using them within your own code, you're probably not thinking in C. You're thinking in lisp or scheme or ruby or ... and trying to write it in C. Learn the C way.
Sometimes, in C, you do this:
typedef struct foo {
unsigned int some_data;
} foo; /* btw, foo_t is discouraged */
To use this new type in an OO-sort-of-way, you might have alloc/free pairs like these:
foo *foo_alloc(/* various "constructor" params */);
void foo_free(foo *bar);
Or, alternatively init/clear pairs (perhaps returning error-codes):
int foo_init(foo *bar, /* and various "constructor" params */);
int foo_clear(foo *bar);
I have seen the following idiom used, in particular in the MPFR library:
struct foo {
unsigned int some_data;
};
typedef struct foo foo[1]; /* <- notice, 1-element array */
typedef struct foo *foo_ptr; /* let's create a ptr-type */
The alloc/free and init/clear pairs now read:
foo_ptr foo_alloc(/* various "constructor" params */);
void foo_free(foo_ptr bar);
int foo_init(foo_ptr bar, /* and various "constructor" params */);
int foo_clear(foo_ptr bar);
Now you can use it all like this (for instance, the init/clear pairs):
int main()
{
foo bar; /* constructed but NOT initialized yet */
foo_init(bar); /* initialize bar object, alloc stuff on heap, etc. */
/* use bar */
foo_clear(bar); /* clear bar object, free stuff on heap, etc. */
}
Remarks: The init/clear pair seems to allow for a more generic way of initializing and clearing out objects. Compared to the alloc/free pair, the init/clear pair requires that a "shallow" object has already been constructed. The "deep" construction is done using init.
Question: Are there any non-obvious pitfalls of the 1-element array "type-idiom"?
This is very clever (but see below).
It encourages the misleading idea that C function arguments can be passed by reference.
If I see this in a C program:
foo bar;
foo_init(bar);
I know that the call to foo_init does not modify the value of bar. I also know that the code passes the value of bar to a function when it hasn't initialized it, which is very probably undefined behavior.
Unless I happen to know that foo is a typedef for an array type. Then I suddenly realize that foo_init(bar) is not passing the value of bar, but the address of its first element. And now every time I see something that refers to type foo, or to an object of type foo, I have to think about how foo was defined as a typedef for a single-element array before I can understand the code.
It is an attempt to make C look like something it's not, not unlike things like:
#define BEGIN {
#define END }
and so forth. And it doesn't result in code that's easier to understand because it uses features that C doesn't support directly. It results in code that's harder to understand (especially to readers who know C well), because you have to understand both the customized declarations and the underlying C semantics that make the whole thing work.
If you want to pass pointers around, just pass pointers around, and do it explicitly. See, for example, the use of FILE* in the various standard functions defined in <stdio.h>. There is no attempt to hide pointers behind macros or typedefs, and C programmers have been using that interface for decades.
If you want to write code that looks like it's passing arguments by reference, define some function-like macros, and give them all-caps names so knowledgeable readers will know that something odd is going on.
I said above that this is "clever". I'm reminded of something I did when I was first learning the C language:
#define EVER ;;
which let me write an infinite loop as:
for (EVER) {
/* ... */
}
At the time, I thought it was clever.
I still think it's clever. I just no longer think that's a good thing.
The only advantage to this method is nicer looking code and easier typing. It allows the user to create the struct on the stack without dynamic allocation like so:
foo bar;
However, the structure can still be passed to functions that require a pointer type, without requiring the user to convert to a pointer with &bar every time.
foo_init(bar);
Without the 1 element array, it would require either an alloc function as you mentioned, or constant & usage.
foo_init(&bar);
The only pitfall I can think of is the normal concerns associated with direct stack allocation. If this in a library used by other code, updates to the struct may break client code in the future, which would not happen when using an alloc free pair.
I want to do some object-oriented style programming in C using polymorphism, where my interface class contains a pointer to a table of functions. Example something like:
/* Implement polymorphism in C, Linux kernel-style */
struct statement {
const struct statement_ops *ops;
struct list_head list; /* when on master input list */
void *private; /* pointer to type-specific data */
};
struct statement_ops {
int (*analyse)(void *private, int pc);
int (*get_binary_size)(void *private);
};
void user(void)
{
struct statement *s = make_a_statement();
if (s->ops->analyse(s->private, foo))
blah blah;
}
I'd like to be able to write something without explicitly passing s->private into every "method". Any ideas? Some macro tricks maybe?
If this is part of the public interface, you can add accessor functions. A hidden benefit is that you can do sanity checks and other work in the accessor. (Note I called the "this" pointer "o", as in "object". I prefer it that way for consistency.)
int statement_analyse (struct statement *o, int pc)
{
assert(pc >= 0);
int ret = o->ops->analyse(o->private, pc);
assert(ret >= 0);
return ret;
}
You can now call this without the explicit passing of "private".
void user(void)
{
struct statement *s = make_a_statement();
if (statement_analyse(s, foo))
blah blah;
}
While it may seem that this provides no benefit, because you still have to implement the accessors, assuming that you want a well defined and robust interface, the accessor functions are the only sane place to put the assertions and the interface documentation. In fact, if you write good assertions, the assertions themselves help document the interface. And once you add sanity checks in the accessors, you don't have to add them in the actual methods they call.
Of course, this approach only makes sense when the function called via the function pointer will be something provided by the user, or in some other way can be different things. If there's a single analyse() method that will always do the same thing, you can simply implement a statement_analyse() that directly does what it needs to do.
Small note: when doing OOP, I prefer to typedef the structs and give them CamelCase names. I use this convention as a way of telling that the struct is opaque and should only be accessed via its public interface. It also looks nicer, though that is subjective. I also prefer having the user allocate the memory for the struct itself, as opposed to the constructor malloc'ing it. That avoids having to handle malloc failure, and makes the program a little bit more efficient.
typedef struct {
...
} Statement;
void Statement_Init (Statement *o);
int Statement_Analyse (Statement *o, int pc);
Unfortunately, writing your methods to allow the passing of a self or this object is the only way to achieve this in C.
You can use macro tricks to hide part of it, but at that point it's not really C any more.
As the other answers say, there is no way to do this without calling the function with the appropriate pointer, but (as Williham Totland suggests) you could use macros to streamline the calls (requires a compiler with variadic macro support):
// macro_call.c
#define C_ARGS(stmnt, func, ...) (stmnt)->ops->func((stmnt)->private, ...)
#define C_NOARGS(stmnt, func) (stmnt)->ops->func((stmnt)->private)
C_ARGS(s, analyse, 1);
C_ARGS(s, lots_of_args, 1, 2, 3, 4);
C_NOARGS(s, no_args);
(The C is for "call".)
Doing the preprocessing on that (via gcc -E macro_call.c) gives:
(s)->ops->analyse((s)->private, 1);
(s)->ops->lots_of_args((s)->private, 1, 2, 3, 4);
(s)->ops->no_args((s)->private);
This is similar to the accessor function version: the macro version is slightly more flexible in some ways, but it is also less safe and could lead to subtle errors and mistakes.
There are two macros because passing no extra arguments to C_ARGS would result in s->ops->func(s->private, ), I think it is possible to fix this, but it is awkward and would require significantly more code (empty __VA_ARGS__ are notoriously hard to deal with).
Is there a "proper" way to implement higher order functions in C.
I'm mostly curious about things like portability and syntax correctness here and if there are more than one ways what the merits and flaws are.
Edit:
The reason I want to know how to create higher order functions are that I have written a system to convert PyObject lists (which you get when calling python scripts) into a list of C structures containing the same data but organized in a way not dependant on the python.h libraries. So my plan is to have a function which iterates through a pythonic list and calls a function on each item in the list and places the result in a list which it then returns.
So this is basically my plan:
typedef gpointer (converter_func_type)(PyObject *)
gpointer converter_function(PyObject *obj)
{
// do som stuff and return a struct cast into a gpointer (which is a void *)
}
GList *pylist_to_clist(PyObject *obj, converter_func_type f)
{
GList *some_glist;
for each item in obj
{
some_glist = g_list_append(some_glist, f(item));
}
return some_glist;
}
void some_function_that_executes_a_python_script(void)
{
PyObject *result = python stuff that returns a list;
GList *clist = pylist_to_clist(result, converter_function);
}
And to clearify the question: I want to know how to do this in safer and more correct C. I would really like to keep the higher order function style but if that is frowned upon I greatly appreciate ways to do this some other way.
Technically, higher-order functions are just functions that take or return functions. So things like qsort are already higher-order.
If you mean something more like the lambda functions found in functional languages (which is where higher order functions really become useful), those are quite a bit harder and can't be done naturally in current standard C. They're just not part of the language. Apple's blocks extension is the best candidate. It only works in GCC (and LLVM's C compiler), but they are really useful. Hopefully something like that will catch on. Here's a few relevant resources:
Apple's documentation on the feature (references some Apple-specific technologies and also addresses Objective-C, but the core block stuff is part of their extensionto C)
Here's a good intro on blocks
Cocoa for Scientists' overview of C blocks
The big problem with implementing higher-order functions in C is that to do anything non-trivial you need closures, which are function pointers augmented with data structures containing local variables they have access to. Since the whole idea behind closures is to capture local variables and pass those along with the function pointer, it's hard to do without compiler support. And even with compiler support it's hard to do without garbage collection because variables can exist outside of their scope, making it hard to figure out when to free them.
This is an answer to the question: how to compose functions in C, which is redirected here.
You can create a data structure to implement a list data type.
that structure can contain function pointers.
#include<stdlib.h>
#include<malloc.h>
typedef (*fun)();
typedef struct funList { fun car; struct funList *cdr;} *funList;
const funList nil = NULL;
int null(funList fs){ return nil==fs; }
fun car(funList fs)
{
if(!null(fs)) return fs->car;
else
{
fprintf(stderr,"error:can't car(nil) line:%d\n",__LINE__);
exit(1);
}
}
funList cdr(funList ls)
{ if(!null(ls)) return ls->cdr;
else
{
fprintf(stderr,"error:can't cdr(nil) line:%d\n",__LINE__);
exit(1);
}
}
funList cons(fun f, funList fs)
{ funList ls;
ls=(funList) malloc(sizeof(struct funList));
if(NULL==ls)
{
fprintf(stderr,"error:can't alloc mem for cons(...) line:%d\n",__LINE__);
exit(1);
}
ls->car=f;
ls->cdr=fs;
return ls;
}
we can write a function comp which applies a list of functions:
type_2 comp(funList fs, type_1 x)
{
return (null(fs)) ? x : car(fs)(comp(cdr(fs),x));
}
An example of how it works. We use (f g h) as a short notation for cons(f,cons(g,cons(h,nil))), which is applied to a given argument x:
comp((f g h),x)
=
f(comp((g h),x))
=
f(g(comp((h),x)))
=
f(g(h(comp(nil,x))))
=
f(g(h(x)))
if you had used the polymorphic list type in a typed language like SML or Haskell the type of comp should be:
comp :: ([a -> a],a) -> a
because in that context all the members in a list have the same type.
C can be more flexible in this sense. Maybe something like
typedef void (*fun)();
or
typedef (*fun)();
you should see what the C manual say about this. And be sure that all contiguous functions have compatible types.
The functions to compose should be pure, i.e. without side effects nor free variables.
In straight c, this is really only done through function pointers, which are both a pain and not meant for this type of thing (which is partially why they are a pain). Blocks (or closures, according to non-apple) are fantastic for this, though. They compile in gcc-4.x or something, and icc something, but regardless thats what you're looking for. Unfortunately, I can't seem to find any good tutorials online, but suffice to say it works something like this:
void iterate(char *str, int count, (^block)(str *)){
for(int i = 0; i < count; i++){
block(list[i]);
}
}
main() {
char str[20];
iterate(str, 20, ^(char c){
printf("%c ", c);
});
int accum = 0;
iterate(someList, 20, ^(char c){
accum += c;
iterate(str, 20, ^(char c){
printf("%c ", c);
});
});
}
obviously this code is pointless, but it it prints each character of a string (str) with a space in between it, then adds all of the characters together into accum, and every time it does it prints out the list of characters again.
Hope this helps. By the way, blocks are very visible in Mac OS X Snow Leopard api-s, and I believe are in the forthcoming C++0x standard, so they're not really that unusual.
If you're keen on doing this in plain C, you need to remember to include the option to pass in a context pointer from the caller of the functor (the higher-order function) to the function passed in. This lets you simulate enough of a closure that you can make things work easily enough. What that pointer points to... well, that's up to you, but it should be a void* in the functor's API (or one of the many aliases for it, such as gpointer in the GLib world or ClientData in the Tcl C API).
[EDIT]: To use/adapt your example:
typedef gpointer (converter_func_type)(gpointer,PyObject *)
gpointer converter_function(gpointer context_ptr,PyObject *obj)
{
int *number_of_calls_ptr = context_ptr;
*number_of_calls_ptr++;
// do som stuff and return a struct cast into a gpointer (which is a void *)
}
GList *pylist_to_clist(PyObject *obj, converter_func_type f, gpointer context_ptr)
{
GList *some_glist;
for each item in obj
{
some_glist = g_list_append(some_glist, f(context_ptr,item));
}
return some_glist;
}
void some_function_that_executes_a_python_script(void)
{
int number_of_calls = 0;
PyObject *result = python stuff that returns a list;
GList *clist = pylist_to_clist(result, converter_function, &number_of_calls);
// Now number_of_calls has how often converter_function was called...
}
This is a trivial example of how to do it, but it should show you the way.
Practically any interesting higher order function application requires closures, which in C entails the laborous and error-prone routine of manually defining and filling struct function arguments.
It's very difficult to do in straight C. It's more possible in C++ (see functors tutorial or Boost's bind and function libraries). Finally, C++0x adds native support for lambda functions, which takes care for you of capturing in closure all of the variables that your funcion depends on.
If you want to create higher order functions, don't use C. There are C solutions to your problem. They may not be elegant, or they may be more elegant that you realize.
[Edit] I suggested that the only way to achieve this was to use a scripting language. Others have called me out on it. So, I'm replacing that suggestion with this: [/Edit]
What are you trying to achieve? If you want to mimic closures, use a language that supports them (you can tie into Ruby, lua, javascript, etc through libraries). If you want to use callbacks, function pointers are ok. Function pointers combine the most dangerous areas of C (pointers and the weak type system), so be careful. Function pointer declarations are not fun to read, either.
You find some C libraries using function pointers because they have to. If you're writing a library, maybe you need to use them, too. If you're just using them within your own code, you're probably not thinking in C. You're thinking in lisp or scheme or ruby or ... and trying to write it in C. Learn the C way.