Re: Callbacks and FFI Techniques
- From: Eric Sosman <esosman@xxxxxxxxxxxxxxxxxxxx>
- Date: Sat, 17 Jan 2009 00:17:04 -0500
Aaron W. Hsu wrote:
I am working on some applications that are designed in two different
languages. Part of it in C and the other part in Scheme. There are a
set of Callbacks which the C side will use which need to be mapped to
Scheme functions. These functions are provided by the Scheme system as
pointers to these functions. I would like to have an intialization
function that I can use to set all these callbacks to the right values
at the start of the program. However, what is the appropriate way to
declare these procedures? I was hoping that I could just assign all the
callback values into an array of type void * and then just have the
right function prototypes used in the declaration of the callbacks.
Is it better to use the void * or actually do everything explicitly,
especially considering that there could be a lot of callbacks?
From the C side, you cannot reliably use a void* (or any
other pointer-to-data) to point at a function. Pointers to
functions can only be stored in pointer-to-function variables.
... which raises a problem. There are as many different
kinds of pointers-to-function as there are different kinds of
functions. A pointer-to-function-returning-int is one kind,
and a pointer-to-function-returning-pointer-to-char is another.
So you either have to declare your pointer variable as a type
that matches the function it points to:
int func1(double, char*);
int (*fptr1)(double, char*) = func1;
.... or else you must use a cast to convert the type:
int func2(double, char*);
void (*fptr2)(void) = ((void)(*)(void))func2;
Both of these can be de-mystified somewhat with a typedef:
int func1(double, char*);
typedef int (*IntOfDblAndString)(double, char*);
IntOfDblAndString fptr1 = func1;
int func2(double, char*);
typedef void (*VoidOfVoid)(void);
VoidOfVoid fptr2 = (VoidOfVoid)func2;
So much for the declarations and initializations (or
assignments). But now you've got another problem: At the
point where you use the pointer to call the function, the
type of the pointer must match the actual type of the called
function. Continuing the examples above,
int result1 = fptr1(3.14, "pi");
.... would be correct, but
int result2 = fptr2(3.14, "pi");
.... would be wrong: The type of fptr2 does not match the type
of func2, the function it points to. If there's a mismatch of
this kind (which there isn't in the fptr1 case), you must correct
it with another cast
int result2 = (int (*)(double, char*))fptr2)(3.14, "pi");
.... whose readability, again, can be improved with a typedef:
int result2 = ((IntOfDblAndString)fptr2)(3.14, "pi");
I'll leave the Scheme side of things for someone else to
explain; I'm a Common Lisp guy, not a Schemer.
--
Eric Sosman
esosman@xxxxxxxxxxxxxxxxxxxx
.
- Follow-Ups:
- Re: Callbacks and FFI Techniques
- From: George
- Re: Callbacks and FFI Techniques
- References:
- Callbacks and FFI Techniques
- From: Aaron W . Hsu
- Callbacks and FFI Techniques
- Prev by Date: Re: How to check for errors when inputting a number
- Next by Date: Re: If 'Han from China' wrote a C book
- Previous by thread: Callbacks and FFI Techniques
- Next by thread: Re: Callbacks and FFI Techniques
- Index(es):
Relevant Pages
|