Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!seismo!columbia!rutgers!mtune!codas!cpsc6a!rtech!wrs!dg
From: dg@wrs.UUCP (David Goodenough)
Newsgroups: comp.lang.c
Subject: Re: Can this be done
Message-ID: <218@wrs.UUCP>
Date: Mon, 6-Jul-87 16:50:40 EDT
Article-I.D.: wrs.218
Posted: Mon Jul  6 16:50:40 1987
Date-Received: Fri, 10-Jul-87 07:32:32 EDT
References: <8125@brl-adm.ARPA>
Reply-To: dg@wrs.UUCP (David Goodenough)
Organization: Wind River Systems, Emeryville, CA
Lines: 133
Summary: Yes

In article <8125@brl-adm.ARPA> jfjr@mitre-bedford.arpa writes:
>
>Now, in another, separate module I have an instance of my
>function pointer structure and the function (call it my_function)
>it points to is also in this module. I make NO attempt to make 
>this function visible outside the module. I make "install"
>visible and in fact I call it to install this structure 
>into the array described above. Can I loop through my array
>and call the functions in it even though none are declared 
>external anywhere? is this legal? possible but not legal??
>done every day?? - how far can I push this?? Any comments
>are welcome

Please find enclosed a quick shell archive that should help explain.

Note that the operative phrase in test2.c when I'm talking about my_func
is that because it's static it can't be referenced _BY_NAME_ outside
test2.c. There's nothing to stop me from using it's name inside test2.c
and passing the resultant pointer around (which is in fact what I'm
doing). _ALL_ that happens when you "static-ize" (? :->) an object is
that the assembler source doesn't have a .globl associated with the name
so the name doesn't make it into the list of names that can be used to
resolve external undefineds, hence if test1.c tried to refer to my_func
with lines of the type:

    extern int my_func();

and

    a = my_func();

you'd get an 'Undefined: _my_func' type of complaint from ld.
--- Cut Here --- Cut Here --- Cut Here --- Cut Here --- Cut Here ---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the '#! /bin/sh' line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (NOT csh) to create the files:
#	A: test1.c
#	B: test2.c
#
if test -f test1.c
then
    echo shar: file test1.c already exists
else
    echo shar: extractng test1.c
    cat <<\##__EOF..test1.c__## >test1.c
#define NULL	0
#define NUM_STR	10

struct					/* this is the structure */
 {
    int _junk1;
    int (*_func)();			/* here is the function pointer */
    int _junk2;				/* the rest (_junk[12]) is filling */
 } list[NUM_STR];

main()
 {
    int i;

    for (i = 0; i < NUM_STR; i++)
      list[i]._func = NULL;		/* set all pointers to NULL */
    install();				/* install my_func */
    call_all();				/* now go call it */
 }

call_all()
 {
    int i;

    for (i = 0; i < NUM_STR; i++)	/* check each structure */
      if (list[i]._func)		/* anything here to call? */
	(*list[i]._func)();		/* yes - go do it */
 }
##__EOF..test1.c__##
if test 614 -eq `wc -c test2.c
extern struct				/* this is the structure */
 {
    int _junk1;
    int (*_func)();			/* here is the function pointer */
    int _junk2;				/* the rest (_junk[12]) is filling */
 } list[];

static my_func()			/* the function we're trying to call
					 * note that it's static so it can't
					 * be referenced _BY_NAME_ outside
					 * this source module */
 {
    printf("Hello World!\n");		/* do something */
 }

install()
 {
    list[0]._func = my_func;		/* install my func into the array */
 }
##__EOF..test2.c__##
if test 498 -eq `wc -c is this legal?
	Yes.
>possible but not legal??
	Irrelevant (see above).
>done every day??
	Probably not.
--
		dg@wrs.UUCP - David Goodenough

					+---+
					| +-+-+
					+-+-+ |
					  +---+