Functions pointers and stuff

Michael Condict mnc at m10ux.UUCP
Fri Mar 31 14:39:34 AEST 1989


In article <3182 at goofy.megatest.UUCP>, djones at megatest.UUCP (Dave Jones) writes:

> From article <1715 at leah.Albany.Edu>, by rds95 at leah.Albany.Edu (Robert Seals):
> > Is there some sneaky way to execute the function when all I know is
> > the name of it, i.e., a pointer to several letters which spell it's name.
> > 
> 
> There's no portable way.  What system are you running?  What version
> of C?

While all the caveats mentioned in previous articles apply, here is a version
that is portable between System V and BSD derived UNIX's, including Suns.  Note
the occurrences of exit(n) for each of the many different things that can go
wrong.  Also note that it makes no attempt to solve the problem of converting
argv[0] into an accessible file name.  It calls the function "Funky" by using
nm to look up the address of the function in the a.out file.  Unfortunately,
this requires one #ifdef BSD, which you should #define when compiling on
Berkeley-derived systems.  The reason is that the BSD nm command prints hex
address, while System V prints decimal.

----------------------------------------------------------------------------
#include <stdio.h>
#include <ctype.h>

void Funky (str) char *str; { printf("Funky: %s\n", str); }

main(argc, argv) int argc; char **argv; {
	char *cp, *fname = "Funky";
	static char addr_str[100], nm_cmd[200];
	long addr = 0;
	FILE *f;
	void (*func_p)();

	printf("Begin test.\n");
	if (!argv[0] || ! argv[0][0]) exit(1);

	/* A command that will print the function address in ASCII: */
	(void)sprintf(nm_cmd, "nm %s | egrep '(^|[^a-zA-Z_])_%s[^a-zA-Z_0-9]'", argv[0], fname);
	if ((f = popen(nm_cmd, "r")) == NULL) exit(2);
	if (!fgets(addr_str, 99, f)) exit(3);
	if (!addr_str[0]) exit(4);

	/* Find the address in the nm output line: */
	for (cp = addr_str; *cp && !isdigit(*cp); cp++) ;
	if (!isdigit(*cp)) exit(5);

#ifdef BSD
		/* Convert ASCII hex representation to binary: */
		(void)sscanf(cp, "%x", &addr);
#else
		addr = atoi(cp);
#endif
	if (!addr) exit(6);

	func_p = (void (*)())addr;
	printf("func_p = 0x%x = %d\n", func_p, func_p);
	(*func_p)("was called.");

	printf("End Test.\n");
	exit(0);
}
-- 
Michael Condict		{att|allegra}!m10ux!mnc
AT&T Bell Labs		(201)582-5911    MH 3B-416
Murray Hill, NJ



More information about the Comp.lang.c mailing list