ilib_build ========== utility for shared library management Calling Sequence ~~~~~~~~~~~~~~~~ :: ilib_build(lib_name,table,files,libs [,makename,ldflags,cflags,fflags,ismex, cc]) Arguments ~~~~~~~~~ :lib_name a character string, the generic name of the library without path and extension. : :table 2 column string matrix giving the table of pairs 'scilab- name', 'interface name' : :files string matrix giving source files needed for shared library creation. Since Scilab 5.3.1, object files are deprecated. : :libs string matrix giving extra libraries needed for shared library creation : :makename character string. The path of the Makefile file without extension. This parameter is useless since Scilab 5.0. Default value to use: []. A warning will be displayed in Scilab 5.3 if you use another value that the default. : :ldflags,cflags,fflags character strings to provide options for the loader, the C compiler and the Fortran compiler. : :ismex Internal variable to specify if we are working with mex or not. : :cc Provide the name of the C compiler. : Description ~~~~~~~~~~~ This tool is used to create shared libraries and to generate a loader file which can be used to dynamically load the shared library into Scilab with `addinter` Many examples are provided in `SCI/modules/dynamic_link/examples` directory. They are all released into the public domain. **Note that a compiler must be available on the system to use this function.** **Languages handle by this function are: C, C++, Fortran and Fortran 90.** On the internal technical level, under GNU/Linux and Mac OS X, the ilib_* function are based on the autotools. First, a configure is executed to detect compilers available. Then, a make is launched with the provided arguments. For more information: `Full technical description of the incremental link / dynamic link`_ Since version 5.3.2, under GNU/Linux, Scilab detects where the libstdc++ is located (thanks to the command gcc -print-search- dirs|grep ^install:|awk '{print $2}' ). Previously, the dynamic link was using the libstdc++ embedded in Scilab. Examples (C code) ~~~~~~~~~~~~~~~~~ :: //Here with give a complete example on adding new primitive to Scilab //create the procedure files `cd`_ TMPDIR; `mkdir`_('example_ilib_build_c'); `cd`_('example_ilib_build_c'); f1=['extern double fun2();' 'void fun1(double *x, double *y)' '{*y=fun2(*x)/(*x);}']; `mputl`_(f1,TMPDIR + '/example_ilib_build_c/fun1.c'); f2=['#include ' 'double fun2(double x)' '{ return( sin(x+1.));}']; `mputl`_(f2,TMPDIR + '/example_ilib_build_c/fun2.c'); //creating the interface file i=['#include ' '#include ' '#include ' '#include ' '' 'extern int fun1 ( double *x, double *y);' '' 'int sci_fun1(char *fname)' '{' ' int iType1 = 0;' ' SciErr sciErr;' ' int m1 = 0, n1 = 0;' ' double *pdVarOne = NULL;' ' int *piAddressVarOne = NULL;' '' ' CheckRhs(1,1);' ' CheckLhs(1,1);' '' ' sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' if (iType1 != sci_matrix)' ' {' ' Scierror(999,_(""%s: Wrong type for input argument #%d: A string expected.\n""), fname, 1);' ' return 0;' ' }' '' ' sciErr = getMatrixOfDouble(pvApiCtx, piAddressVarOne, &m1, &n1, &pdVarOne);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' fun1(pdVarOne, pdVarOne);' ' LhsVar(1) = 1;' ' return 0;' '}']; `mputl`_(i,TMPDIR + '/example_ilib_build_c/sci_fun1.c'); //creating the shared library (a gateway, a Makefile and a loader are //generated. files=['fun1.c','fun2.c','sci_fun1.c']; ilib_build('build_c',['fun1','sci_fun1'],files,[]); // load the shared library `exec`_ loader.sce; //using the new primitive fun1(33) Examples (C code - previous Scilab API < 5.2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: `cd`_ TMPDIR; `mkdir`_('example_ilib_build_c_old'); `cd`_('example_ilib_build_c_old'); //Here with give a complete example on adding new primitive to Scilab //create the procedure files f1=['extern double fun2();' 'void fun1(double *x, double *y)' '{*y=fun2(*x)/(*x);}']; `mputl`_(f1,'fun1.c') f2=['#include ' 'double fun2(double x)' '{ return( sin(x+1.));}']; `mputl`_(f2,'fun2.c'); //creating the interface file i=['#include ""stack-c.h""' '#include ""stackTypeVariable.h""' '#include ""version.h""' '#if SCI_VERSION_MAJOR <= 5' '#if SCI_VERSION_MINOR < 2' ' #error ""This example is obsolete see help ilib_buid""' '#endif' '#endif' '' 'extern int fun1 ( double *x, double *y);' 'int intfun1(char *fname)' '{' ' int m1,n1,l1;' ' CheckRhs(1,1);' ' CheckLhs(1,1);' ' GetRhsVar(1, MATRIX_OF_DOUBLE_DATATYPE, &m1, &n1, &l1);' ' fun1(stk(l1),stk(l1));' ' LhsVar(1) = 1;' ' return 0;' '}']; `mputl`_(i,'intfun1.c') //creating the shared library (a gateway, a Makefile and a loader are //generated. files=['fun1.c','fun2.c','intfun1.c']; ilib_build('ilib_c_old',['scifun1','intfun1'],files,[]); // load the shared library `exec`_ loader.sce //using the new primitive scifun1(33) Examples (C++ code) ~~~~~~~~~~~~~~~~~~~ :: `cd`_ TMPDIR; `mkdir`_('example_ilib_build_cpp'); `cd`_('example_ilib_build_cpp'); i=['#include ' 'extern ""C"" {' '#include ' '#include ' '#include ' '#include ' '' 'int sci_cppfind(char *fname)' '{' '' ' SciErr sciErr;' ' int *piAddressVarOne = NULL;' ' char *pStVarOne = NULL;' ' int iType1 = 0;' ' int lenStVarOne = 0;' ' int m1 = 0, n1 = 0;' '' ' int *piAddressVarTwo = NULL;' ' char *pStVarTwo = NULL;' ' int iType2 = 0;' ' int lenStVarTwo = 0;' ' int m2 = 0, n2 = 0;' '' ' int m_out = 0;' ' int n_out = 0;' '' ' sciErr = getVarAddressFromPosition(pvApiCtx, 1, &piAddressVarOne);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' sciErr = getVarType(pvApiCtx, piAddressVarOne, &iType1);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' if (iType1 != sci_strings)' ' {' ' Scierror(999,_(""%s: Wrong type for input argument #%d: A string expected.\n""), fname, 1);' ' return 0;' ' }' '' ' sciErr = getVarAddressFromPosition(pvApiCtx, 2, &piAddressVarTwo);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' sciErr = getVarType(pvApiCtx, piAddressVarTwo, &iType2);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' if (iType2 != sci_strings)' ' {' ' Scierror(999,_(""%s: Wrong type for input argument #%d: A string expected.\n""), fname, 2);' ' return 0;' ' }' '' ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarOne, &m1, &n1, &lenStVarOne, &pStVarOne);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' pStVarOne = new char[lenStVarOne + 1];' ' if (pStVarOne == NULL)' ' {' ' Scierror(999,_(""%s: Memory allocation error.\n""),fname);' ' return 0;' ' }' '' ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo, &m2, &n2, &lenStVarTwo, &pStVarTwo);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' pStVarTwo = new char[lenStVarTwo + 1];' ' if (pStVarTwo == NULL)' ' {' ' Scierror(999,_(""%s: Memory allocation error.\n""),fname);' ' return 0;' ' }' '' ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarOne, &m1, &n1, &lenStVarOne, &pStVarOne);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' sciErr = getMatrixOfString(pvApiCtx, piAddressVarTwo, &m2, &n2, &lenStVarTwo, &pStVarTwo);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' std::string myMessage(pStVarOne);' ' std::string search(pStVarTwo);' ' delete pStVarTwo;' ' delete pStVarOne;' ' double dOut = 0.0;' '' ' if (myMessage.find(search) != std::string::npos) {' ' dOut = myMessage.find(search); /* The actual operation */' ' } else {' ' dOut = -1; /* Substring not found */' ' }' ' m_out = 1;' ' n_out = 1;' ' sciErr = createMatrixOfDouble(pvApiCtx, Rhs + 1, m_out, n_out, &dOut);' ' if(sciErr.iErr)' ' {' ' printError(&sciErr, 0);' ' return 0;' ' }' '' ' LhsVar(1) = Rhs + 1;' ' return 0;' '} /* extern ""C"" */' '}']; `mputl`_(i,TMPDIR + '/example_ilib_build_cpp/sci_cppfind.cxx'); //creating the shared library (a gateway, a Makefile and a loader are //generated. files = ['sci_cppfind.cxx']; ilib_build('ilib_build_cpp',['cppfind','sci_cppfind'],files,[]); // load the shared library `exec`_ loader.sce; // Small test to see if the function is actually working. if cppfind("my very long string","long") <> 8 pause, end if cppfind("my very long string","very") <> 3 pause, end if cppfind("my very long string","short") <> -1 pause, end Examples (C++ code - previous Scilab API < 5.2) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: `cd`_ TMPDIR; `mkdir`_('example_ilib_build_cpp_old'); `cd`_('example_ilib_build_cpp_old'); i=['#include ' 'extern ""C"" {' '#include ""stack-c.h""' '#include ""version.h""' '#if SCI_VERSION_MAJOR <= 5' '#if SCI_VERSION_MINOR < 2' ' #error ""This example is obsolete see help ilib_buid""' '#endif' '#endif' '' 'int sci_cppfind(char *fname) {' ' int m1 = 0, n1 = 0, l1;' ' char *inputString1, *inputString2;' ' int m2 = 0, n2 = 0, l2;' ' int m3 = 0, n3 = 0;' ' double *position = NULL; /* Where we will store the position */' ' CheckRhs(2,2); /* Check the number of input argument */' ' CheckLhs(1,1); /* Check the number of output argument */' ' GetRhsVar(1, ""c"", &m1, &n1, &l1); /* Retrieve the first input argument */' ' inputString1=cstk(l1);' ' GetRhsVar(2, ""c"", &m2, &n2, &l2); /* Retrieve the second input argument */' ' inputString2=cstk(l2);' ' std::string myMessage (inputString1);' ' std::string search (inputString2);' ' m3=1;n3=1;' ' position = new double[1];' ' if (myMessage.find(search) != std::string::npos) {' ' position[0] = myMessage.find(search); /* The actual operation */' ' } else {' ' position[0] = -1; /* Substring not found */' ' }' ' CreateVarFromPtr(Rhs+1,""d"",&m3,&n3,&position); /* Create the output argument */' ' LhsVar(1) = Rhs+1;' ' delete[] position;' ' return 0;' '}' '}']; `mputl`_(i,'sci_cppfind.cxx'); //creating the shared library (a gateway, a Makefile and a loader are //generated. files=['sci_cppfind.cxx']; ilib_build('foo_old',['cppfind','sci_cppfind'],files,[]); // load the shared library `exec`_ loader.sce // Small test to see if the function is actually working. if cppfind("my very long string","long") <> 8 pause, end if cppfind("my very long string","very") <> 3 pause, end if cppfind("my very long string","short") <> -1 pause, end Examples (Fortran 90 code) ~~~~~~~~~~~~~~~~~~~~~~~~~~ :: `cd`_ TMPDIR; `mkdir`_('example_ilib_build_f90'); `cd`_('example_ilib_build_f90'); sourcecode=['subroutine incrdoublef90(x,y)' ' implicit none' ' double precision, intent(in) :: x' ' double precision, intent(out) :: y' ' y=x+1' 'end subroutine incrdoublef90']; `mputl`_(sourcecode,'incrdoublef90.f90'); libpath=`ilib_for_link`_('incrdoublef90','incrdoublef90.f90',[],'f'); `exec`_ loader.sce n=1.; m=`call`_("incrdoublef90",n,1,"d","out",[1,1],2,"d"); if `abs`_(m-2.)>%eps then pause,end n=2.; m=`call`_("incrdoublef90",n,1,"d","out",[1,1],2,"d"); if `abs`_(m-3.)>%eps then pause,end Example: How to use cflags arguments ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :: `cd`_ TMPDIR; `mkdir`_('example_ilib_build_cflag'); `cd`_('example_ilib_build_cflag'); csource = ['#include ' '#include ' '#include ' '' 'int sci_examplecflag(char *fname)' '{' '' '#ifdef __MYDEF_FOR_THIS_FUNCTION__' 'sciprint(""__MYDEF_FOR_THIS_FUNCTION__ detected !!!\n"");' '#else' 'sciprint(""__MYDEF_FOR_THIS_FUNCTION__ not detected !!!\n"");' '#endif' '' ' LhsVar(1) = 0;' ' return 0;' '}']; `mputl`_(csource, TMPDIR + '/example_ilib_build_cflag/sci_cflags.c'); //creating the shared library (a gateway, a Makefile and a loader are //generated.) files=['sci_cflags.c']; // here we uses cflags argument and we define __MYDEF_FOR_THIS_FUNCTION__ ilib_build('gw_c_flags',['examplecflag','sci_examplecflag'], files, [], [], '', '-D__MYDEF_FOR_THIS_FUNCTION__'); // load the shared library `exec`_ loader.sce; //using the new primitive examplecflag() // __MYDEF_FOR_THIS_FUNCTION__ detected !!! `ulink`_(); `exec`_ cleaner.sce; // and now ilib_build('gw_c_flags',['examplecflag','sci_examplecflag'], files, []); `exec`_ loader.sce; examplecflag() // __MYDEF_FOR_THIS_FUNCTION__ not detected !!! See Also ~~~~~~~~ + `addinter`_ new functions interface dynamic link at run time. + `link`_ dynamic linker + `ilib_compile`_ ilib_build utility: executes the Makefile produced by ilib_gen_Make + `ilib_gen_Make`_ utility for ilib_build: produces a Makefile for building shared libraries + `ilib_gen_gateway`_ utility for ilib_build, generates a gateway file. + `ilib_gen_loader`_ utility for ilib_build: generates a loader file + `ilib_for_link`_ utility for shared library management with link + `api_scilab`_ api_scilab is the Scilab interface to read/write data from/to Scilab memory History ~~~~~~~ Version Description 5.4.0 This function no more accepts files with ".o" or ".obj" extensions as source files. .. _Full technical description of the incremental link / dynamic link: http://wiki.scilab.org/Full%20technical%20description%20of%20the%20incremental%20link .. _ilib_for_link: ilib_for_link.html .. _ilib_compile: ilib_compile.html .. _addinter: addinter.html .. _link: link.html .. _ilib_gen_loader: ilib_gen_loader.html .. _api_scilab: api_scilab.html .. _ilib_gen_Make: ilib_gen_Make.html .. _ilib_gen_gateway: ilib_gen_gateway.html