Function pointers and use of the special ... operator

S

signuts

#include <stdio.h>
#include <stdlib.h>

#include <dlfcn.h>
/* non standard header */

int main(int argc, char **argv) {
void *libtest;

void (*p)(void *,...);

libtest = dlopen("libtest.so", RTLD_LAZY);
if (libtest == NULL) {
printf("%s\n", dlerror());
exit(EXIT_FAILURE);
}

p = dlsym(libtest, "test2");

if (p == NULL) {
printf("%s\n", dlerror());
exit(EXIT_FAILURE);
}

(*p)(NULL, "two");

dlclose(libtest);
exit(EXIT_SUCCESS);
}


This is the code snip I am using to demonstrate the use of function
pointers. I would like to know the difference between declaring a function
pointer like 'void (*p)(void *, void *)' when you could easily have a
"generic" one declared like the one displayed in this example.

I have two functions, test and test2 in libtest.so. test has no arguments
and test2 has two strings, I found I can call the functions using this
"magic" pointer.

I am hoping for a response back, thanks.

- Sig
 
J

Jack Klein

#include <stdio.h>
#include <stdlib.h>

#include <dlfcn.h>
/* non standard header */

int main(int argc, char **argv) {
void *libtest;

void (*p)(void *,...);

libtest = dlopen("libtest.so", RTLD_LAZY);
if (libtest == NULL) {
printf("%s\n", dlerror());
exit(EXIT_FAILURE);
}

p = dlsym(libtest, "test2");

What's the return type in the prototype for dlsym()? There is no
defined, legal conversion between pointer to any type of object and
pointer to any type of function. As far as C is concerned they are
apples and oranges and there is no way at all to change one into the
other.

You can apply a cast, but the behavior is quite literally undefined.
if (p == NULL) {
printf("%s\n", dlerror());
exit(EXIT_FAILURE);
}

(*p)(NULL, "two");

It is never necessary to use an asterisk on a pointer to function to
call the function to which it points. The line above does nothing
different than just coding:

p(NULL, "two");
dlclose(libtest);
exit(EXIT_SUCCESS);
}


This is the code snip I am using to demonstrate the use of function
pointers. I would like to know the difference between declaring a function
pointer like 'void (*p)(void *, void *)' when you could easily have a
"generic" one declared like the one displayed in this example.

I have two functions, test and test2 in libtest.so. test has no arguments
and test2 has two strings, I found I can call the functions using this
"magic" pointer.

I am hoping for a response back, thanks.

- Sig

Dammit, doesn't anybody understand how to use a proper signature line
any more? There is a specification for it, and most newsreaders
understand and handle it automatically, if YOU FOLLOW THE
SPECIFICATION.

A proper signature line consists of three characters plus an end of
line, "-- ". Anything else, such as your name, starts on the line
AFTER this. Set your news software properly, please.

The C standard specifically differentiates between varargs functions
(with ...) and functions with fixed numbers of arguments. Calling one
of these type with a prototype or cast that causes the compiler to
think it is calling the other type is undefined behavior and will
specifically cause a crash on many platforms.

Consider:

void f1(int, int);
void f2(int, ...);

Then the function calls:

f1(1, 2);
f2(1, 2);

The compiler is allowed to pass the arguments (1 and 2) in totally
different ways to these two functions, and on many processor types it
will, although perhaps not on the register-starved x86. Specifically
it might pass the arguments to functions with a small fixed number of
arguments in processor registers, whereas the second must be formatted
in a way to allow for processing a variable argument list.

So the reason not to use a function pointer with ... somewhere in the
argument list to call a function that actually takes a fixed number of
arguments is that it is illegal C and just plain won't work on many
platforms.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++ ftp://snurse-l.org/pub/acllc-c++/faq
 
S

signuts

dlopen returns a void pointer to the "handle" of the library, probably
where the library is loaded into memory or something.
What's the return type in the prototype for dlsym()? There is no
defined, legal conversion between pointer to any type of object and
pointer to any type of function. As far as C is concerned they are
apples and oranges and there is no way at all to change one into the
other.

void *dlsym(void *handle, char *symbol);
You can apply a cast, but the behavior is quite literally undefined.


It is never necessary to use an asterisk on a pointer to function to
call the function to which it points. The line above does nothing
different than just coding:

p(NULL, "two");
Hey, thanks for the tip, not only does this make the code look cleaner,
its also makes more sense to me as well!
Dammit, doesn't anybody understand how to use a proper signature line
any more? There is a specification for it, and most newsreaders
understand and handle it automatically, if YOU FOLLOW THE
SPECIFICATION.

I obviously didn't understand the importance of the uniform news
signature. Looks like I better read that RFC too.
A proper signature line consists of three characters plus an end of
line, "-- ". Anything else, such as your name, starts on the line
AFTER this. Set your news software properly, please.

Simply amazing!
The C standard specifically differentiates between varargs functions
(with ...) and functions with fixed numbers of arguments. Calling one
of these type with a prototype or cast that causes the compiler to
think it is calling the other type is undefined behavior and will
specifically cause a crash on many platforms.

Consider:

void f1(int, int);
void f2(int, ...);

Then the function calls:

f1(1, 2);
f2(1, 2);

The compiler is allowed to pass the arguments (1 and 2) in totally
different ways to these two functions, and on many processor types it
will, although perhaps not on the register-starved x86. Specifically
it might pass the arguments to functions with a small fixed number of
arguments in processor registers, whereas the second must be formatted
in a way to allow for processing a variable argument list.

So the reason not to use a function pointer with ... somewhere in the
argument list to call a function that actually takes a fixed number of
arguments is that it is illegal C and just plain won't work on many
platforms.

Thank you for the help.

- Today my signature was unfairly discriminated
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,780
Messages
2,569,611
Members
45,270
Latest member
TopCryptoTwitterChannels_

Latest Threads

Top