Firstly, as it has been noted already, you failed to allocate memory for your 'speaker' object in 'NewSpeaker'. Without the unnecessary clutter it would look as follows
speaker* NewSpeaker(void)
{
speaker *s = malloc(sizeof *s);
s->say = say;
return s;
}
Note, that there's no cast on the result of the malloc, no type name in the 'sizeof' argument and the function parameter list is declared as '(void)', not just '()'.
Secondly, if you want to be able to create non-dynamic objects of your 'speaker' type, you might want to provide an in-place initialization function first, and then proceed from there
speaker* InitSpeaker(speaker* s)
{
assert(s != NULL);
s->say = say;
return s;
}
speaker* NewSpeaker(void)
{
void *raw = malloc(sizeof(speaker));
return raw != NULL ? InitSpeaker(raw) : NULL;
}
Finally, if you really want to create something like virtual C++ methods, you need to supply each method with a 'this' parameter (to get access to other members of your object). So it should probably look something like
typedef struct speaker
{
void (*say)(struct speaker *this, char *msg);
} speaker;
void say(speaker *this, char *dest)
{
printf("%s",dest);
}
This, of course, will require you to pass the corresponding argument every time you call a "method", but there's no way around this.
Additionally, I hope you know that you need "method" pointers in your "class" for "virtual methods" only. Ordinary (non-virtual) methods don't need such pointers.
Finally, a "traditional" C++ class imlementation doesn't store virtual method pointers inside each instance of the class. Instead, they are placed in a separate table (VMT), pointer to which is added to each instance. This saves a lot of memory. And this, BTW, makes especially good sense when you implement inheritance.