dynamic loaders

daniel thom swanback swanbacd at handel.cs.colostate.edu
Fri Apr 26 13:53:28 AEST 1991


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 at handel.cs.colostate.edu



More information about the Comp.lang.c mailing list