Dynamic loader / argument overloading example


Subject: Dynamic loader / argument overloading example
From: Kevin Cameron x3251 (Kevin.Cameron@nsc.com)
Date: Tue Dec 17 2002 - 16:10:42 PST


The attached files demonstrate how the argument checking and dynamic
loading work.

lib.cc contains too functions "foo" with different arguments and a
locator which is
registered when test loads the library.

test.c creates contexts and calls the locator with different argument specs.

It works for g++ 2.95.2 on Solaris 2.8.

./test should give:

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

The code is cut down to a minimum to demonstrate routine selection on
arguments,
but the calls are those in the proposal (except for svcInitLib which
I'll add).

Regards,
Kev.

PS: For a different compiler, compile the code and do an "nm liblib.so"
then sustitute
the strings given to the dlsym call in lib.cc


Makefile

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

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

static void *self;

int foo(svcContext *cp,double arg) {
  fprintf(stderr,"Called (double)\n");
  return arg * 3;
}

int foo(svcContext *cp,int arg) {
  fprintf(stderr,"Called (int)\n");
  return arg * 3;
}

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__FP10svcContexti";

  if (0 == strcmp(args[1],"double")) ep = "foo__FP10svcContextd";

  
  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)(svcContext *,int);
typedef int (*fn_r)(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)(&foo_i,2);
      fprintf(stderr,"foo(2) = %d\n",i);
    }

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


test




This archive was generated by hypermail 2b28 : Tue Dec 17 2002 - 16:13:22 PST