Dynamic loader / argument overloading example2 + proposal update


Subject: Dynamic loader / argument overloading example2 + proposal update
From: Kevin Cameron x3251 (Kevin.Cameron@nsc.com)
Date: Wed Dec 18 2002 - 10:19:37 PST


I added a bit more code to the example to demonstrate how the linker phase
can set up user-context data for the actual calls.

In lib.cc where the right routine is selected there are assignments to the
"p_context->user_context" field. That field is re-used in the subsequent
calls either "foo" - the int version has a context value 3, and the double
version uses 3.6. The output from test is then:

 Locator for $root registered
 Looking for int foo(int)
 Looking for int foo(double)
 Called (int)
 foo(2) = 6
 Called (double)
 foo(2.0) = 7

I also added in the instance handle passing for completeness (although it
does nothing in this example).

If there is any other functionality folks would like to see demonstrated
I can
easily add it.

I also attached an updated version of the proposal including the svcInitLib
extension (for initialazing DLLs).

Regards,
Kev.

#include <stdio.h>
#include <varargs.h>
#include <dlfcn.h>
#include <link.h>

extern "C" {
#include "./sv2c.h"
}

static void *self;

int foo(handle ip, svcContext *cp,double arg) {
  fprintf(stderr,"Called (double)\n");
  return arg * cp->user_context.dbl;
}

int foo(handle ip, svcContext *cp,int arg) {
  fprintf(stderr,"Called (int)\n");
  return arg * cp->user_context.data[0];
}

static svcExtFunc myBinder( void *context,
                            char *modname,
                            char *inst_name,
                            char *rtn_name,
                            svcContext *p_context,...)
{
  svcExtFunc rtn_addr = 0;
  char *args[3];
  va_list pv;

  va_start(pv);

  args[0] = va_arg(pv, char *);

  fprintf(stderr,"Looking for %s %s",args[0],rtn_name);
  int a = 1;
  char *punc = "(";
  while (args[a] = va_arg(pv, char *)) {
    fprintf(stderr,"%s%s",punc,args[a++]); punc = ",";
  }
  fprintf(stderr,")\n");

  char *ep = 0;

  // You can put a lot of code here to calculate arbitrary
  // names - I'm cheating since I know we've only got two

  if (0 == strcmp(args[1],"int")) {
    ep = "foo__FPvP10svcContexti";
    p_context->user_context.data[0] = 3;
  }

  if (0 == strcmp(args[1],"double")) {
    ep = "foo__FPvP10svcContextd";
    p_context->user_context.dbl = 3.6;
  }
  
  svcExtFunc rp = 0;

  if (ep) {
    rp = (svcExtFunc) dlsym(RTLD_SELF,ep);
  }

  return rp;
}

extern "C" int svcInitLib(void *lib_handle)
{
  self = lib_handle;

  svcRegisterLocator(myBinder,0,"$root",0);
}

#include <stdio.h>
#include <dlfcn.h>
#include <link.h>

#include "sv2c.h"

svcContext foo_i,
           foo_d;

struct {
  svcLocater func;
  void *locator_context;
  char *module_spec;
  int capabilities;
} Locator_List;

int svcRegisterLocator(svcLocater locator,
                       void *locator_context,
                       char *module_spec,
                       int capabilities) {

  Locator_List.func = locator;

  fprintf(stderr,"Locator for %s registered\n",module_spec);
  
}

typedef void (*init_fn)();

typedef int (*fn_i)(handle,svcContext *,int);
typedef int (*fn_r)(handle,svcContext *,double);

main()
{
  void *lib = dlopen("./liblib.so",RTLD_NOW),
       *init = dlsym(lib,"svcInitLib");

  if (init) {
    fn_i fi;
    fn_r fr;

    (*(init_fn)init)(lib);

    fi = (fn_i)(*Locator_List.func)(0, "$root",
                                         "$root",
                                         "foo",
                                         &foo_i,
                                         "int",
                                         "int",0
                                         );

    fr = (fn_r)(*Locator_List.func)(0, "$root",
                                         "$root",
                                         "foo",
                                         &foo_d,
                                         "int",
                                         "double",0
                                         );

    if (fi) {
      int i = (*fi)(0,&foo_i,2);
      fprintf(stderr,"foo(2) = %d\n",i);
    }

    if (fr) {
      int i = (*fr)(0,&foo_d,2.0);
      fprintf(stderr,"foo(2.0) = %d\n",i);
    }
  }
}


sv2c.pdf



This archive was generated by hypermail 2b28 : Wed Dec 18 2002 - 10:22:17 PST