SYNTAX:
xpfExternalFunction (dllName , functionName : STRING;
inArguments, outArguments : INTEGER; argument1, . . . , argumentN : GENERIC) functionValue : GENERIC;
The xpfExternalFunction function invokes a function that is external to the EDMexpressVM.
Argument:: |
Description: |
dllName |
name of the dll where the external function is located. |
functionName |
name of the external function |
functionValue |
the value returned from the external function |
inArguments |
number of input arguments |
outArguments |
number of output arguments |
argument1, . . . , argumentN |
The arguments, input arguments before output arguments. |
The external function must be present in a DLL, on WINDOWS or in a shared library on UNIX platforms. The location of the DLL must be present in the PATH on WINDOWS and in the shared library search path on UNIX platforms. The name of the environment variable which denotes the shared library search path is LD_LIBRARY_PATH on Solaris, IRIX and Linux, whereas it is LIBPATH on AIX and SHLIB_PATH on HPUX.
The prototype of the external function is fixed and must be:
long function_name( long nin_arg,
long nout_arg,
SdaiSelect result,
SdaiSelect userArgs);
nin_arg : number of input arguments
nout_arg : number of output arguments
result : function value as seen from the originating xpfExternalFunction
userArgs : array of arguments, where the output arguments should be placed after the input arguments.
function value : status code.
Since SdaiSelect is used, sdai.h must be included in ?function_name? ( #include ), and the location of sdai.h must be present in the include search path when compiling. Please note that the function value of the native function is a status code and that edmi error codes are applicable. The actual function value as seen from the originating xpfExternalFunction should be placed in the result argument.
This interface is useful when implementing a new external library which adopts to this way of interfacing, but existing ready made libraries have to be layered underneath the native EDM layer. Needless to say, such actual ?target? libraries have to be present in the library path as well.
See example below.
Map using external function:
SCHEMA_MAP mapp;
GLOBAL
DECLARE src INSTANCE OF SOURCE_SCHEMA myschema;
DECLARE tar INSTANCE OF TARGET_SCHEMA myschema;
END_GLOBAL;
STATEMENTS;
LOCAL
sum : INTEGER;
status : INTEGER;
lineno : INTEGER;
error : STRING;
average : REAL;
END_LOCAL;
– Calculate the sum and average of (1,2,3,4,5)
status := xpxExternalFunction('mylib.so','sum',sum,5,1,1,2,3,4,5,average);
lineno := xpxCURRENTLINE-1;
if(status = 0) THEN
xpxPrintf('\nsum: %d',sum);
xpxPrintf('\naverage: %f',average);
ELSE
xpxGetErrorText(status,error);
xpxPrintf('\nError at line %d : %s',lineno,error);
END_IF;
xpxPrintf('\n-----------------------------------------------');
ON_ERROR_DO;
xpxPrintf('\nError at line %d : ',lineno);
xpxPrintf('%s',xpfGetErrorText(xpxExceptionId.errCode));
xpxThrow;
END_ON_ERROR_DO;
– Calculate the sum and average of (11,12,13,14,15) as function
--xpxPrintf('\nsum: %d',xpfExternalFunction('mylib.so','sum',0,1,11,12,13,14,15,average));
lineno := xpxCURRENTLINE+1;
sum := xpfExternalFunction('mylib.so','sum',5,1,11,12,13,14,15,average);
xpxPrintf('\nsum: %d',sum);
xpxPrintf('\naverage: %f',average);
END_STATEMENTS;
END_SCHEMA_MAP;
Implementation of external function.
#include "sdai.h"
long sum(long nin_arg, long nout_arg, SdaiSelect result, SdaiSelect userArgs)
/*
Calculates the sum and average of 'nin_arg' numbers.
The sum is passed in the 'result' argument and will hence be
returned as function value by the originating xpfExternalFunction call.
The average is passed as the one and only output argument.
*/
{
SdaiSelect inarg,outarg;
long i,sum,ival;
float average;
if(nin_arg <= 0) return(edmiE_NUMBER_OF_ARGS_IN_CALL);
if(nout_arg != 1) return(edmiE_NUMBER_OF_ARGS_IN_CALL);
sum = 0;
inarg = userArgs;
/*
Calculate the sum.
*/
for(i=0; i<nin_arg; ++i){
/* Obtain argument */
if(inarg->type != sdaiINTEGER) return(edmiEARGSINCALL);
ival = inarg->value.intVal;
sum += ival;
/* Increment argument pointer */
++inarg;
}
/*
Deposit the sum in the result SdaiSelect container.
*/
result->type = sdaiINTEGER;
result->value.intVal = sum;
/*
Deposit the average in the one and only output argument.
*/
average = ((float)sum)/nin_arg;
outarg = inarg;
outarg->type = sdaiREAL;
outarg->value.realVal = average;
return(0);
}
See also xpxExternalFunction