Chapter Contents

Previous

Next
loadm

loadm



Dynamically Load a Load Module

Portability: SAS/C extension


SYNOPSIS
DESCRIPTION
RETURN VALUE
ERRORS
CAUTIONS
PORTABILITY
IMPLEMENTATION
USAGE NOTES
EXAMPLES
Example 1.1 simple case
Example 1.2 dynamic loading modules with multiple functions
Example 1.3 dynamic loading under CMS
RELATED FUNCTIONS


SYNOPSIS

#include <dynam.h>;

void loadm(const char *name, __remote /* type */ (**fpp)());


DESCRIPTION

loadm loads an executable module named by the argument string name and stores a C function pointer in the location pointed to by the argument fpp . If the module has been loaded already, the pointer stored in fpp points to the previously loaded copy. If the module name in the first argument string is prefixed with an asterisk, a private copy of the module is loaded. Note that fpp may reference a function returning any valid type of data.


RETURN VALUE

loadm provides an indirect return value in the form of a function pointer that addresses the entry point of the loaded module. If the module is in C, calling the returned function always transfers control to the _dynamn function of the module.

If the module to be loaded cannot be found, a NULL is stored in the location addressed by fpp .


ERRORS

Various user ABENDs, notably 1217 and 1218, may occur if overlays of library storage are detected while dynamic loading is in progress.


CAUTIONS

The first argument string may be no more than eight characters long, not counting a leading asterisk.

The second argument must be a pointer to an object declared as "pointer to function returning (some C data type)."

Note that a module to be loaded by loadm cannot have the entry point defined in the last 16 bytes of the load module. The library inspects this portion of the loaded module, and may ABEND if 16 bytes of data are not present. This situation can arise only if the entry point is an assembler (or other non-C) routine.


PORTABILITY

loadm is not portable. Be aware of system dependencies involving where load modules may be located and how module names are specified for your operating system.


IMPLEMENTATION

The implementation of loadm necessarily varies from operating system to operating system. Under OS/390, modules to be loaded must reside in STEPLIB, a task library, or the system link list. Under CMS, modules to be loaded may reside in DYNAMC LOADLIB or in other locations defined by use of the addsrch routine. Under CICS, modules to be loaded must reside in a library in the DFHRPL concatenation and must be defined to CICS.


USAGE NOTES

addsrch does not verify the existence of a location, for example, DYNAMC LOADLIB. Because in some circumstances the logic of a program may not require that a location be searched, no verification is done until loadm cannot find a load module in any location defined earlier in the search order. addsrch fails only if its parameters are ill-formed.

If loadm determines that a location is inaccessible (for example, the LOADLIB does not exist), the location is marked unusable, and no attempt is made to search it again.


EXAMPLES

The use of loadm is illustrated by three examples. The first demonstrates the use of the command for a very simple situation without operating-system dependencies, while second and third examples are designed to run under OS/390 and CMS respectively.

The second example creates a dynamic load module that includes a table of pointers to functions which may be called dynamically from the calling load module. This example runs under OS/390 and has been designed to provide a framework that can be expanded upon in complete application.

The third example presents a hypothetical situation under CMS in which

  1. the load module is created

  2. the load module's location is added to the list of locations from which modules can be loaded ( addsrch )

  3. the load module is loaded ( loadm )

  4. the load module is deleted from the search order list ( delsrch ).


Example 1.1 simple case

#include <dynam.h>

int (*fp)(); 
   /* Load a load module named "ADD" and call it. */ 
loadm("ADD",&  fp); 
sum = (*fp)(1, 3); 
. 
. 
.


Example 1.2 dynamic loading modules with multiple functions

Example 1.2 illustrates techniques for managing load modules containing multiple functions. This example includes illustrative OS/390 JCL, but the techniques illustrated in the example are also applicable to CMS.

STEP I. Put the following declarations in a common header file and name it DYNTABLE:

struct funcdef {           /* structure definition for functions     */
   int (*func1)();
   int (*func2)();
                            /* More functions can go here.            */
};

typedef struct funcdef *fptrtable;  /* pointer to list of funcdefs    */

Make sure the header library containing DYNTABLE is allocated so that it will be included when you compile the following source code.

STEP II. Create the following C source file and name it DYNAMIC. This file will be compiled and linked to create a dynamic load module. The _dynamn function returns to its caller a structure of function pointers that can be used to call the individual functions of the load module.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <lcio.h>
#include <dynam.h>
#include "dyntable.h"

   /* _dynamn function that returns a list of function pointers which */
   /* can be used to invoke other functions in the load module        */
fptrtable _dynamn(void) {
      /* Initialize function pointer table.                           */
   static struct funcdef dyntab = {&func1, &func2 /* ... */};
      /* Return pointer to table with the new contents.               */
   return(&dyntab);
}

int func1() {
  printf("func1() was successfully dynamically called!!!\n");
  return(0);
}

int func2() {
  printf("func2() was successfully dynamically called!!!\n");
  return(0);
}

DYNAMIC must be compiled using the sname compiler option to override the default assignment of _dynamn as the section name. It may be compiled as re-entrant using the rent compiler option. (Note that JCL changes are required if norent compilation is needed.) During linking, the ENTRY=DYN (or DYNNK for norent ) parameter must be specified.

STEP III. Create the following C source file and name it DYNMLOAD. This code demonstrates how to dynamically load the DYNAMIC load module and how to call the functions pointed to by the dyntab table:

#include <stdio.h>
#include <string.h>
#include <dynam.h>
#include "dyntable.h"

fptrtable(*fpdyn)();  /* _dynamn function pointer prototype       */

int rc1, rc2;         /* return codes from calling func_1         */
                      /* and func_2                               */

fptrtable table;      /* table of function pointer and names      */
                      /* returned from _dynamn                    */               */
main()
{
      /* Load DYNAMIC.                                            */
   loadm("DYNAMIC", &fpdyn);

      /* Call _dynamn and return table of function pointers and   */
      /* name of load module.                                     */
   table = (*fpdyn)();

      /* Call func1 using function pointer from table.            */
   rc1 = (*table->func1)();
   printf("Dynamically called func1() with rc = %d \n", rc1);

      /* Call func2 using function pointer from table.            */
   rc2 = (*table->func2)();
   printf("Dynamically called func2() with rc = %d \n", rc2);

   unloadm(fpdyn);
   return;
}

STEP IV. Modify the following JCL, which is used to compile and link the DYNAMIC and DYNMLOAD source files and then execute the resulting load module. (Note that site-dependent job statements should be added.)

//*
//*   COMPILE and LINK module that uses a _dynamn routine that passes
//*   its caller back a list of function pointers which are used to
//*   invoke other functions in the load module
//*
//COMPDYNM EXEC LC370CL,ENTRY=DYN,PARM.C='RENT SNAME(DYNAM)'
//C.SYSLIN   DD DSN=userid.SASC.OBJ(DYNAMIC),DISP=OLD
//C.SYSIN    DD DSN=userid.SASC.SOURCE(DYNAMIC),DISP=SHR
//*
//LKED.SYSLMOD  DD DSN=userid.SASC.LOAD(DYNAMIC),DISP=OLD
//*
//*
//*   COMPILE and LINK module that dynamically loads the DYNAMIC
//*   load module and calls functions within the load module
//*   using the structure of function pointers returned.
//*
//CLEMAIN EXEC LC370CLG
//C.SYSLIN   DD DSN=userid.SASC.OBJ(DYNMLOAD),DISP=OLD
//C.SYSIN    DD DSN=userid.SASC.SOURCE(DYNMLOAD),DISP=SHR
//*
//LKED.SYSLMOD  DD DSN=userid.SASC.LOAD(DYNMLOAD),DISP=OLD
//


Example 1.3 dynamic loading under CMS

A C source file, NEPTUNE C (listed below), is to be dynamically loaded and executed. The file contains the function neptune .

#include <stdio.h>

void neptune(char *p) {
   puts(p); 
   return; 
}

STEP I. Make the function neptune into a separate, loadable module by link-editing the TEXT file into a CMS LOADLIB file. The following steps are required:

  1. Rename the function to _dynamn .
    #include <stdio.h>
    
    void _dynamn(char *p) { 
       puts(p);
       return; 
    }

    All C load modules (except the one that includes main , of course) must define one function named _dynamn .

  2. Recompile NEPTUNE C, using the sname compiler option to override the default assignment of _dynamn as the sname. See Chapter 7, "Compiler Options," in the SAS/C Compiler and Library User's Guide for more information about the sname compiler option.

  3. Link-edit the resulting NEPTUNE TEXT file using the CMS command LKED. The LIBE and NAME options of the LKED command can be used to specify the name of the output LOADLIB file and member name, respectively. For example,
    LKED NEPTUNE (LIBE DYNAMC NAME NEPTUNE

The LKED command creates the file DYNAMC LOADLIB, containing the member NEPTUNE (assuming the LOADLIB did not already exist).

STEP II. The function neptune now exists in a form loadable by loadm . Invoke loadm to load the module as follows:

#include <dynam.h>
main()
{
   int (*fp)();               /* Declare a function pointer */
   loadm("NEPTUNE",&fp);      /* Load NEPTUNE               */
      if (fp) {               /* Check for errors           */
         (*fp)("Hello, Neptune, king of the C!");
         unloadm(fp);         /* Delete NEPTUNE             */
      }
      else
         puts("NEPTUNE failed to load.");
    exit(0);
}

STEP III. The previous step used the default search location DYNAMC LOADLIB (see addsrch ); thus, no call to addsrch is required. If you use some other filename for the LOADLIB, specify it in a call to addsrch before invoking loadm . The following is an example:

#include <dynam.h>

main() 
{
   SEARCH_P sp;                    /* Declare a SEARCH_P value  */
   int (*fp)();
      /* specify "NEWLIB LOADLIB *" */
   sp = addsrch(CMS_LDLB,"NEWLIB *",""); 
   loadm("NEPTUNE",&  fp); 
   if (fp) { 
      (*fp)("Hello, Neptune, king of the C!");  
      unloadm(fp);
   }
   else
      puts("NEPTUNE failed to load.");
   delsrch(sp);  /* remove NEWLIB LOADLIB from the search order */ 
   exit(0); 
}

Since the NEPTUNE load module is relocatable, it can be loaded as a CMS nucleus extension by the NUCXLOAD command. Then the following calls cause NEPTUNE to be accessed from the nucleus extension:

sp = addsrch(CMS_NUCX,"","");
loadm("NEPTUNE",&fp);

The function must exist as a nucleus extension before invoking loadm . This facility is useful, for example, in testing a single load module that you plan to replace in an existing LOADLIB.


RELATED FUNCTIONS


Chapter Contents

Previous

Next

Top of Page

Copyright © 2001 by SAS Institute Inc., Cary, NC, USA. All rights reserved.