[comp.lang.c] dynamic loaders

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.