/****************************************************************************** Copyright (c) 2006 Unigraphics Solutions, Inc. Unpublished - All Rights Reserved *******************************************************************************/ /* The following example is implemented in two parts. An external NX Open API program loads a shared library that is built as an internal NX Open API program. Both programs may be compiled and linked using ufcomp and uflink. Note: When compiling an external program no interactive libraries can be included. Use the "-noui" link with uflink on Unix. This is the external program, uf_eg5b.c. The external program calls UF_initialize() and UF_terminate. It is the external program that loads and executes the internal shared library. The internal program should not call UF_initialize and UF_terminate since the external program calls these functions. Your internal program may not contain calls to functions that are internal and interactive when the shared library executes in the context of an external NX Open API program. This is because internal only routines are not available to external NX Open API programs. The contents of ufd_load.h is as follows: int ep_a(int argc, char *argv[]); int ep_b(int argc, char *argv[]); */ /***************************************************************** After creating ufd_example_shlib (the source of which is in uf_eg5a.c, compile and link the following code as an external NX Open API program. Execute the program with ufd_example_shlib available in the current working directory (pwd). ******************************************************************/ #include #include #include #include #define MAX_INPUT_SIZE (8) /* Larger than needed input buffer. */ typedef int (*XMPL_f_p_t)( int argc, char *argv[] ); #define XMPL_SHLIB ("ufd_example_shlib") #define XMPL_FNC_A ("ep_a") #define XMPL_FNC_B ("ep_b") /***************************************************************** * * Loads a library and finds the function entry point specified by * the symbol name (sym), if necessary. Calls the function with * supplied arguments and returns status. The function pointer is * output for future use. * ***/ static int execute_lib( char *lib, /* I - Library Name. */ char *sym, /* I - Symbol Name. */ int argc, /* I - Argument Count. */ char *argv[], /* I - Arguments. */ XMPL_f_p_t *fnc ) /* IO - Function Pointer for 'sym'.*/ { int error; /* Load library if necessary... */ if( NULL == *fnc ) { UF_load_f_p_t generic_fnc; if( !(error = UF_load_library( lib, sym, &generic_fnc )) ) { *fnc = (XMPL_f_p_t) generic_fnc; } else /* Library load failed... */ { char message[133]; UF_get_fail_message( error, message ); fprintf( stderr, "ERROR: While loading \"%s\" (%s)...\n\t%s\n", lib, sym, message ); } } else error = ERROR_OK; /* Execute function... */ if( NULL != *fnc ) error = (**fnc)( argc, argv ); return( error ); } /***************************************************************** * * A simple program to demonstrate dynamic loading and * unloading of shared libraries using UF_load_library * and UF_unload_library. The program allows the user * to select one of two libraries to load and execute, * unload both libraries, or terminate the program. Target * function prototypes are expected to match the 'C' 'main' * prototype (i.e. int fnc(int argc, char *argv[])). * ***/ /*ARGSUSED*/ extern int main( int argc, char *argv[] ) { int error; if( !(error = UF_initialize()) ) { int done; done = 0; do { char input[MAX_INPUT_SIZE+1]; /* Display user choices... */ printf( "\n\n" ); printf( " 1 - Load and execute \"%s\" function.\n", XMPL_FNC_A ); printf( " 2 - Load and execute \"%s\" function.\n", XMPL_FNC_B ); printf( " 3 - Unload libraries.\n" ); printf( " 4 - Terminate.\n\n" ); printf( "Enter selection: " ); /* Get user selection. */ fgets( input, sizeof(input), stdin ); printf( "\n\n" ); /* Selection must be a single digit. */ if( isdigit(input[0]) && '\n' == input[1] ) { static XMPL_f_p_t fnc_a = NULL; static XMPL_f_p_t fnc_b = NULL; /* Process selection... */ switch( input[0] ) { case '1': /* Load and execute first function... */ { char *xmpl_argv[] = { XMPL_SHLIB, /* Library to load. */ XMPL_FNC_A, /* Function to execute. */ "Called function ep_a in library ufd_example_shlib." }; int xmpl_argc = sizeof(xmpl_argv) / sizeof(*xmpl_argv); error = execute_lib( xmpl_argv[0], xmpl_argv[1], xmpl_argc, xmpl_argv, &fnc_a ); } break; case '2': /* Load and execute second function... */ { char *xmpl_argv[] = { XMPL_SHLIB, /* Library to load. */ XMPL_FNC_B, /* Function to execute. */ "Called function ep_b in library ufd_example_shlib." }; int xmpl_argc = sizeof(xmpl_argv) / sizeof(*xmpl_argv); error = execute_lib( xmpl_argv[0], xmpl_argv[1], xmpl_argc, xmpl_argv, &fnc_b ); } break; case '3': /* Unload library... */ UF_unload_library( XMPL_SHLIB ); fnc_a = NULL; fnc_b = NULL; break; case '4': /* Finished - set termination flag. */ done = 1; break; default: /* Input character is out of range... */ fprintf( stderr, "\nERROR: Invalid selection.\n" ); break; } } else fprintf( stderr, "\nERROR: Select with digit only.\n" ); } while( !done && !error ); UF_terminate(); } else { char message[133]; UF_get_fail_message( error, message ); fprintf( stderr, "ERROR: %s\n", message ); } return( 0 ); }