Path: utzoo!attcan!uunet!husc6!mailrus!uflorida!novavax!proxftl!bill From: bill@proxftl.UUCP (T. William Wells) Newsgroups: comp.lang.c Subject: Re: Structure pointer question Summary: that's not the way to do it. Message-ID: <424@proxftl.UUCP> Date: 5 Jul 88 06:25:39 GMT References: <361@teletron.uucp> <8074@brl-smoke.arpa> <4524@haddock.isc.com> <391@teletron.UUCP> Organization: Proximity Technology, Ft. Lauderdale Lines: 99 In article <391@teletron.UUCP>, andrew@teletron.UUCP (Andrew Scott) writes: > Now that my original question has been answered, I have another: > > Suppose that I've constrcuted a library of functions that operate on a > "generic" data structure called 'struct message'. This structure is an > incomplete type; the library functions merely deal with pointers to this > structure but not with the fields within. > > It is now permissible to use this library with different declarations of > 'struct message' *in the same program*? I'm not planning on converting > between multiple kinds of "messages", I just want to have multiple modules > in the program able to use the previously constructed library with data > structures applicable to (and used in) only one module. > > My initial guess is that it would work, given that C requires all structure > pointers to have the same format and provided that I compile the different > modules of the program seperately (so that the compiler doesn't see the > multiple declarations). Strictly speaking, such a program does not have to work, however... I pointed out that, unless some code generation is done at link time, a compiler can't really make assumptions about incomplete structure types and thus can't use different representations for structure pointers; however, another message points out that there is one relatively common environment where this is not true: interpreters. I'd say that, if you are using a system with separately compiled modules that what you are doing is likely to work, but if you did it in a interpreter system, that it may not. Also, I know of one compiler system that could defer part of the code generation to link time. The Amsterdam Compiler Kit's program building goes compile, link, and assemble; the linker can fix up structure pointer references if necessary. The compiler used for MINIX is based on this compiler system. The correct solution is to have your library deal with void *. If a raw void * bothers you, use typedef void *MESSAGE; and then type everything as MESSAGE. You will also probably want to have macros that do the references to library functions if these pointers are to be passed as arguments or returned as values by functions in the library. I'll guess that you are building some kind of message passing system and that your library has something to do with queueing and dequeing. On that presumption, here is how I might write an enqueue function. These are in the public include file: #define msg_queue(x) (lib_msg_queue((void *)(x))) extern int lib_msg_queue(); extern void *msg_dequeue(); These are in the library itself: typedef struct Q_ELT { struct Q_ELT *q_next; void *q_message; } Q_ELT; int lib_msg_queue(msg) void *msg; { Q_ELT *qptr; if (!(qptr = (Q_ELT *)malloc(sizeof(Q_ELT)))) { return (-1); } qptr->q_message = msg; ...enqueue the message return (0); } void * msg_dequeue() { Q_ELT *qptr; void *msg; qptr = ... dequeue the message; if (!qptr) { return (0); } msg = qptr->q_message; free(qptr); return (msg); } If you have a compiler with prototypes, your job is even easier. Change the name of lib_msg_queue to msg_queue and place this in the public include file: extern int msg_queue(void *msg); extern void *msg_dequeue(void); Does that help?