Re: How do I create a function in my library for passing user callback function



On 14 Apr, 03:24, "Bill Reid" <hormelf...@xxxxxxxxxxxxxxxx> wrote:
Angus <nos...@xxxxxxxxx> wrote in message
news:fttgg7$g7k$1$8302bc10@xxxxxxxxxxxxxxxxxxx


I am writing a library which will write data to a user defined callback
function.  The function the user of my library will supply is:

int (*callbackfunction)(const char*);

In my libary do I create a function where user passes this callback
function?  How would I define the function?

I tried this

callbackfunction clientfunction;

void SpecifyCallbackfunction(cbFunction cbFn)

what is cbFunction?

{
   clientfunction = cbFn;
}

Then called like this:
clientfunction(sz);  // sz is a C-string.

But program crashes with access violation when attempt to call
clientfunction

What am I doing wrong?

Well, just about everything, and most pertinently, asking a question
here, the land of the technically-incompetent trolls...but here's how
you do it:

before making remarks like that you should make *really*
sure you havn't made any foolish errors in your code...

Oh, sorry I forgot you didn't post any code!



In the header file for your library, declare the function as follows:

extern void my_library_function(int (*)(const char*));

(Note: as somebody may tell you, "extern" is a redundant
linkage specifier for function declarations, but I use it anyway
and therefore you should too!)

a substantial body of people don't, so consider missing it out.



Now write your library function that takes the callback as
a parameter in the source file for your library:

void my_library_function(int my_callback_function(const char*)) {
    int my_callback_return;
    char *my_string;

    ... /* generic stuff done here, probably "build up" my_string  */

    my_callback_return=my_callback_function(my_string);

    ... /* more generic stuff maybe, maybe check my_callback_return  */
    }

Now, for any source file that you want to use that generic
my_library_function(), you can call it by first #include'ing the
library header file, then defining a specific callback function that
matches the declaration in the header file:

int my_specific_function(const char* my_string) {

    ... /* do something with string, probably print it, right?  */
    }

Then you can call your library function with the callback anywhere
in your source file, as well as any other functions that you have defined
that match the callback signature:

void my_function(void) {

    ... /* stuff happens here, whatever, maybe nothing, who knows  */

    my_library_function(my_specific_function);

    ... /* and whatever else  */
    }

And that's "all" there is to it...not that bad once you get the hang of
it, just follow the pattern above,

no! don't follow the pattern above!

sometimes you have to really "think"
about what the perfect "signature" will be for all the various callbacks
you want for a generic library function, what all data you need to
pass for all possible conditions...

no not at all.

Ok. Here's a more compact form of your code with a driver added.


/***********/
/* the code that Bill Reid didn't write */

extern void my_library_function (int (*)(const char*));

void my_library_function(int my_callback_function(const char*)) /*
<--- error */
{
int my_callback_return;
char *my_string = "";
my_callback_return=my_callback_function (my_string);
}

int my_specific_function (const char* my_string)
{
return 0;
}

/* driver added by me */
int main (void)
{
my_library_function (my_specific_function);
return 0;
}
/**********/

and my compiler does this

Compiling...
reid.c
C:\bin\reid.c(6) : warning C4028: formal parameter 1 different from
declaration

So let's try this pattern:-

/* in the header */
typedef int (*Callback)(const char*);
void my_library_function (Callback);


/* in the library */
void my_library_function (Callback my_callback_function)
{
int my_callback_return;
char *my_string = "";
my_callback_return = my_callback_function (my_string);
}


/* in the caller's code */
int my_specific_function (const char* my_string)
{
return 0;
}

/* driver added by me */
int main (void)
{
my_library_function (my_specific_function);
return 0;
}


the typedef makes life *much* easier.

So how to construct the typedef?

Suppose the callback is going to look something like this
int f1 (int x)

put a typedef in front of it and change the name
to your convention for types (I start a typename
with an uppercase letter)
typedef int F1 (int x);

put a * in front of the function name and bracket the name
and the *.
typedef int (*F1) (int x);

remove the argument names if you like.
typedef int (*F1) (int);

You can then use this wherever you need the function
pointer.

A slightly more complicated example
char *f2 (int x, double x, F1 callback);
typedef char* (*F2) (int, double, F1);

You even return function pointers
F1 setCB (F1 new_call);
typedef F1 (*SetCB) (F1);


Some people prefer to typedef the function then the
pointerness is not hidden.

typedef int F1 (int);
typedef char* F2 (int, double, F1*);

And now I'm guilty of Reid's syndrome, I havn't
compiled this. But I did compile the pattern
I recommend (and use).


--
Nick Keighley

As I recall, OSI dealt with TCP/IP by just admitting it into the spec
as a variation of existing levels. This is akin to dealing with an
Alien face hugger by allowing it to implant its embryo in your body.
.



Relevant Pages

  • Bypassing Personal Firewalls
    ... typedef SOCKET (int, int, int); ... typedef int (__stdcall *func_connect)(SOCKET, const struct sockaddr ... typedef HANDLE (LPCTSTR, DWORD, DWORD, ...
    (Bugtraq)
  • Bypassing Personal Firewalls
    ... typedef SOCKET (int, int, int); ... typedef int (__stdcall *func_connect)(SOCKET, const struct sockaddr ... typedef HANDLE (LPCTSTR, DWORD, DWORD, ...
    (Vuln-Dev)
  • Re: formal parameter 1 different from declaration?
    ... Here is the typedef one: ... typedef LR (HWND, long, int, int); ... struct tagWnd; // forward declaration ... takes a struct tagHwnd and the other takes a long. ...
    (microsoft.public.vc.language)
  • Re: I dont understand typedef example
    ... * Using typedef, declare 'func' to have type ... 'function taking two int arguments, ... declared ptr as a pointer object that can points to a function of the ...
    (comp.lang.c)
  • Re: I dont understand typedef example
    ... Using typedef, declare 'func' to have type ... 'function taking two int arguments, ...
    (comp.lang.c)