swanbacd@handel.cs.colostate.edu (daniel thom swanback) (04/26/91)
Gentlemen, This is a problem that I have encountered frequently and has produced a stall in my current efforts. Conceptually, I need to be able to use the type of the data as a variable itself. The routine to write needs to be able to call other functions at run-time. The problems it has produced are a direct consequence of the following: 1. Every function needs a return of any valid C type 2. Every function takes on a variable length parameter list 3. Every parameter in the list has to be declared as any valid C type. To solve this problem, I have attempted to use combinations of #definitions, structures, pointers to functions, direct calls in case statements, nonlocal control transfers, and variable length function definitions. To date, the effort has not gone well. Consider any function definition: type1 functx(type2, type3, type4, ...); What is required is to be able to call this function through another function, for example: type1 = loader(functx, type2, type3, type4, ...); Problems: 1. What was first attempted was a pointer to the function to call. Most texts simply avoid the following problem, namely, once the address is loaded to the pointer, to call it requires a variable of the same type to accept its return type, and that the correct number of variables need to be present and of, at best, an evolvable type. This removes the possibility of storing functions in libraries for run time use(in a useful capacity). For example: int (*ptr)(), result ; ptr = getch; result = (*ptr)(); /* notice: no variable is used in the call */ ptr = putch; result = (*ptr)(var1); /* however, here we have called the function with its REQUIRED variable of int type.*/ Imagine writing a routine to call either of these functions. We could set up a library of type pointers, struct int_functions{ int (*ptr)()[2]; }; struct (for the rest of every type possible)_functions { type (*ptr_toit)(); }; struct library { struct int_functions int_lib; struct (for every data type here) ... etc... (for every type possible!) }; static struct library lib; lib.int_lib.ptr = {getch, putch, ...}; the problem then becomes obvious, the only way to declare a pointer to any possible user defined or c library routine is to declare every pointer to a function returning a specific type that could ever exist! (not to mention user defined type(S), struct, union names, etc...) On this note, pointers to functions in a library is useful in all of the very select programming situations that seldom exist. 2. Attempted next was to set the function name directly into a case, i.e: switch (functx){ case putch: ??? = putch(var1); case getch: ??? = getch(); } however, here there is no possible means to malloc every data type that may be returned by a user function. How would one, at least on a dynamic level, say, allocate a variable of "struct mystructure *" to receive the return type of the function? Further, it is possible to retrieve the data from the loader argument list by using the variable argument list operations. But again, how would one create the innumerable data types to hold these values? 3. Possibly, one could in the source, physically write the return types and the correctly typed variable of correct number into a case statement from another program to prime the loader, switch (functx){ case #105: struct mystructure *funct1(var1, var2); case #99 : int funct2(var1, var2, var2, var2, var3); { where "varn" is the correct data type of a dynamically allocated variable array. The problem with this is obvious. Again, the data type must be used as a variable else must appear as the physical recipient of the return type. This is a key concept of a menuing system. It must have the ability to run a user selected function from a variable number of instances where its invocation would be required. The alternative is to create a giant case statement, one for each menu that would run the user's function in a manner that meets the specifications. However, the source code size will increase in a manner that is unacceptably large and impossible to transport, as a menuing package, to another product. If there exists a book, a person I could talk to in person or within a reasonable calling distance, a feature of the language I have missed, on this issue, I will respond promptly. ANY assistance in this regard would be greatly appreciated. Thanks, Dan Swanback swanbacd@handel.cs.colostate.edu
stachour@sctc.com (Paul Stachour) (04/26/91)
swanbacd@handel.cs.colostate.edu (daniel thom swanback) writes: >Gentlemen, > This is a problem that I have encountered frequently and has >produced a stall in my current efforts. Conceptually, I need to >be able to use the type of the data as a variable itself. The >routine to write needs to be able to call other functions at >run-time. The problems it has produced are a direct consequence >of the following: > 1. Every function needs a return of any valid C > type > 2. Every function takes on a variable length > parameter list > 3. Every parameter in the list has to be > declared as any valid C type. > The problem of dynamic linking and loading is an old one. It is a well-solved problem. The question of "what do I need to do it?" is indeed the proper one. I would remond your search begin at the "classical" manual that talks about the system that first did effective, well-done, dynamic linking. This is the Multics system, and the manual I would recommend for you is the Multics Programmer's Reference Manual, Order Number AG91. In the back, it has the complete data-structure definitions (in PL/1, but you can translate) for what you need. It includes about 65 different data-types; you can easily extend it as you need. This can be ordered through your "Bull" representative I'm told. It might not be possible, since Multics was discontinued, but it's where I would start. -- Paul Stachour SCTC, 1210 W. County Rd E, Suite 100 stachour@sctc.com Arden Hills, MN 55112 [1]-(612) 482-7467
torek@elf.ee.lbl.gov (Chris Torek) (04/26/91)
In article <14530@ccncsu.ColoState.EDU> swanbacd@handel.cs.colostate.edu (daniel thom swanback) writes: >Gentlemen, > This is a problem that I have encountered frequently and has >produced a stall in my current efforts. Conceptually, I need to >be able to use the type of the data as a variable itself. Then you are using the wrong language. Go read about Smalltalk, or Lisp flavors, or something. If you are bound and determined to do this in C, you must implement your own type function binding systems. You may want to just write a complete C interpreter, although from your description it sounded as though you might be able to omit one or two things. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
gwyn@smoke.brl.mil (Doug Gwyn) (04/27/91)
In article <14530@ccncsu.ColoState.EDU> swanbacd@handel.cs.colostate.edu (daniel thom swanback) writes: >The problems it has produced are a direct consequence of the following: > 1. Every function needs a return of any valid C > type > 2. Every function takes on a variable length > parameter list > 3. Every parameter in the list has to be > declared as any valid C type. The real problem is that these requirements are absurd when combined with an additional requirement of implementation in C. C is a typed language and these requirements explicitly require violation of typing. While I could suggest all sorts of techniques for trying to "somehow" achieve this impossible task, in my opinion the necessity of such requirements should be challenged. If it turns out that there really is a firm requirement for these attributes, then consider defining an interpreted language in which to implement such operations. (You could reasonably implement the interpreter in C.) >This is a key concept of a menuing system. It must have the >ability to run a user selected function from a variable number of >instances where its invocation would be required. I don't understand why you couldn't impose constraints on the "user selection functions" that would permit a reasonable C implementation.
torek@elf.ee.lbl.gov (Chris Torek) (04/28/91)
In article <12532@dog.ee.lbl.gov> I left out a word: >If you are bound and determined to do this in C, you must implement >your own type [and] function binding systems. Without the `and' it makes little sense. Note that although the subject asked for a dynamic loader (which can be implemented in machine-dependent C), but the body of the article also asked for, in essense, some way to define `in advance' all of the possible function call protocols. This also can be implemented in machine-dependent C, but it then becomes compiler-dependent as well. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
wollman@emily.uvm.edu (Garrett Wollman) (04/29/91)
In article <12573@dog.ee.lbl.gov> torek@elf.ee.lbl.gov (Chris Torek) writes: >Note that although the subject asked for a dynamic loader (which can >be implemented in machine-dependent C), but the body of the article >also asked for, in essense, some way to define `in advance' all of >the possible function call protocols. This also can be implemented in >machine-dependent C, but it then becomes compiler-dependent as well. There already exist several bits&pieces of code to do dynamic loading. There is the GNU dld library, which runs on Suns and a few others; several operating systems (such as SunOS 4.1 and Umax 4.3, to name two) have built-in support for it; if you can stomach the object-oriented preprocessor called `class' and the fact that it takes up 80 Meg on a Sparc, there is also CMU's Andrew system, which supports Vaxen, MIPSEL, Sparcs, Sun-3s, HPs of some vintage, and Mach-i386 (to name a few). The only problem with the latter is the size and terms of distribution may not be amenable to everyone, and it doesn't yet work on SunOS 4.1. -GAWollman Garrett A. Wollman - wollman@emily.uvm.edu Disclaimer: I'm not even sure this represents *my* opinion, never mind UVM's, EMBA's, EMBA-CF's, or indeed anyone else's.
chap@art-sy.detroit.mi.us (j chapman flack) (04/30/91)
Dan Swanback <swanbacd@handel.cs.colostate.edu> writes of a menuing system system that has, at run time, to make vectored calls to functions that take different parameter lists and return values of different types and sizes. He details a number of implementation approaches he has tried. I wonder if this is a case (don't take this the wrong way, Dan) of too much implementation before enough analysis. The posting devoted a lot of space to various implementation details and very little space to what the system needs to do. Perhaps there are other approaches that circumvent the problem altogether. The stated problem is *not* easy to solve in C, and a working solution will probably depend significantly on implementation- specific details of the C being used. If the project really does require the approach in question, I might suggest that C is not the most appropriate language. The solution might be much simpler and prettier in, say, Lisp, or another language with built-in dynamic binding. Just my $0.02.... -- Chap Flack Their tanks will rust. Our songs will last. chap@art-sy.detroit.mi.us -Mikos Theodorakis Nothing I say represents Appropriate Roles for Technology unless I say it does.