Application-specific C/C++ userexits are provided with the help of dynamic libraries (.DLLs under Windows, .SO under Unix). Their libraries are linked in DataView by reference entries in the repository and are loaded by the application when required. Compared with static linking, dynamic linking has the advantage that the application does not need to be translated or linked again if your made some changes or improvements to userexit or if you want to add or remove ibraries.
A C/C++ userexit library can only be dynamically linked if it exists in the bin directory of the server application.
/** * * This is the entry function of this module. * * It is called by the Module Management with some of the * following events: * * Mod_EVENT_INIT - module loaded, userexits may be added * Mod_EVENT_START - module activated * Mod_EVENT_STOP - module deactivated * Mod_EVENT_EXIT - module terminated * Mod_EVENT_BATCH - Batched EDB session started * Mod_EVENT_SERVER - ECI-Server EDB session started * Mod_EVENT_GRAPH - Graphic EDB session started * Mod_EVENT_TRACE_ON - Enable trace output * Mod_EVENT_TRACE_OFF - Disable trace output * * At initialization time, this module may add userexits by * calling the functions * * Dux_open() and Dux_addCustomUsx() * * If this function returns an error code, it MUST close the * handle to release the userexits added so far by calling * * Dux_close() * * Only functions of the DUX interface may be called inside the * INIT event: initialization is not finished at this point. * * If the function receives an unknown event, it should return * zero to be compatible with future event codes. * * @param eEvent event to process * @return 0 = ok, >0 = error * */ int Sample_Entry(Mod_Event eEvent) { /* The handle for adding the userexits */ static Dux_Handle hDux = NULL; int err = 0; /* Print a message if tracing is active */ if(ITrace) fprintf(stderr, MOD_DBGNAME "Entry function called (event = %d)\n", eEvent); /* Examine the event */ switch(eEvent) { case Mod_EVENT_RESET: /* Reset the module */ /* * Try to initialize again */ case Mod_EVENT_INIT: /* Initialize the module */ IStarted = 0; ITrace = epdbg_isDebugged(MOD_ID); /* Request the userexit handle */ hDux = Dux_open(MOD_NAME, MOD_VERSION); if(!hDux) { fprintf(stderr, MOD_DBGNAME "Could not obtain a handle!\n" ); } else { /* Handle ok, add all userexits */ err = addUserexits(hDux); /* Add the request listener */ if(!err) { err = Mod_addRequestListener(RequestListener, 0); if(err != 0) { fprintf(stderr, MOD_DBGNAME "Could not add request listener (error code %d)\n", err); } } /* Cleanup if a serious error occurred */ if(err != 0) { fprintf(stderr, MOD_DBGNAME "Closing handle (error code %d)\n", err); Dux_close(hDux); hDux = NULL; } } break; case Mod_EVENT_EXIT: /* Terminate the module */ if(hDux) { Mod_removeRequestListener(RequestListener); Dux_close(hDux); hDux = NULL; } break; case Mod_EVENT_BATCH: /* Batch mode, no user interaction */ case Mod_EVENT_SERVER: /* ECI Server mode */ IBatch = 1; /* Caution: may be followed by Mod_EVENT_GRAPH if JavaClient is used! */ break; case Mod_EVENT_GRAPH: /* Interactive mode */ IBatch = 0; break; case Mod_EVENT_START: /* Enable the module */ IStarted = 1; break; case Mod_EVENT_STOP: /* Disable the module */ IStarted = 0; break; case Mod_EVENT_TRACE_ON: /* Enable tracing */ ITrace = 1; break; case Mod_EVENT_TRACE_OFF: /* Disable tracing */ ITrace = 0; break; default: /* Unknown event */ if(ITrace) fprintf(stderr, MOD_DBGNAME "Unknown event code %d\n", eEvent); break; } return err; } /** * * This function adds all userexits of this library to the * specified Dux handle. * * @param hDux the handle for adding the userexits * @return 0 - OK * >0 - could not add userexit(s) * */ static int addUserexits(Dux_Handle hDux) { /* Table with all userexits */ static Dux_UsxTableEntry taUsxTable[] = { /* Add your userexits here, the name should have your library prefix */ { MOD_PREFIX "_tst_usx", TestUsx, Dux_USXTYPE_MENU}, { MOD_PREFIX "_art_cfr", ItemForm, Dux_USXTYPE_MENU} }; int err = 0, i=0; for(i=0; !err && (i < TAB_SIZE(taUsxTable)); i++ ) { switch(Dux_addCustomUsx(hDux, taUsxTable[i].cpName, taUsxTable[i].pFunc, taUsxTable[i].eType)) { case 0: break; case ERR_DUX_CONFLICT: fprintf(stderr, MOD_DBGNAME "Someone has stolen my userexit name '%s'\n", taUsxTable[i].cpName); err = 1; break; default: fprintf(stderr, MOD_DBGNAME "Could not add userexit '%s'\n", taUsxTable[i].cpName); err = 2; break; } } return err; } /** * * This function is a listener for requests sent by the * server process to every listener that has been added * by a call to Mod_addRequestListener. * The server aborts the processing of the requested action * if one of the listeners returns a non-zero value. * * Possible request are: * Mod_REQUEST_START - module should start * Mod_REQUEST_STOP - module should stop * Mod_REQUEST_EXIT - module should terminate * Mod_REQUEST_SHUTDOWN - user wants to logout * * If the function receives an unknown request or if it * is not interested in the request, it MUST return * Mod_ACCEPT_REQUEST to be compatible with future request * codes. * * @param eRequest request sent by the server process * @return 0 - Request accepted * >0 - Request rejected * */ static int RequestListener(Mod_Request eRequest) { int iRc = Mod_ACCEPT_REQUEST; /* Print a message if running in debug mode */ if(ITrace) fprintf(stderr, MOD_DBGNAME "Request listener called (request = %d)\n", eRequest); /* Examine the request */ switch(eRequest) { case Mod_REQUEST_EXIT: /* Reject EXIT if userexits must be kept alive */ iRc = Mod_REJECT_REQUEST; break; default: /* * Unknown or irrelevant request */ break; } return iRc; }
The entry function is immediately called after loading the library. The function adds the implemented userexits and registers the event listener to receive control events.