venerdì 7 marzo 2008

calling of C/C++ routines from the Windows™ version of Scilab using Microsoft™'s Visual C++ compiler

tratto da qui


Visual C++ by Dave Sidlauskas

This section illustrates the calling of C/C++ routines from the Windows™ version of Scilab using Microsoft™'s Visual C++ compiler. The process is quite simple.

  1. Use VC++ create a DLL containing the C functions.

  2. In Scilab, use link() to load the DLL functions.

  3. Use fort() to run the functions.

In a little more detail:

  1. Use VC++ to create a DLL.

    Start VC++, click FILE, NEW, and select WIN 32 Dynamic Link-Library. Give it a name and location and click OK. Then select Empty DLL and click Finish.

    Prepare a source file and insert it into the project (Project, Add To Project). Then build the project (F7).

    A sample source file is shown below. The declaration extern "C" declspec(dllexport) is critical. Using this, the function name is exported correctly with no name mangling. This type of declaration is covered in the VC++ on-line documentation if you wish more details.

    Also note that C files that are to be executed by a call to fort() are always void, returning no value. Values are returned via pointers in the function parameter list. For example, the parameter *out in matcpy_c is the return value for that function.

    extern "C" _declspec(dllexport) void matset_c(double *mat,
    const int *nrows,
    const int *row,
    const int *col,
    double *val);

    extern "C" _declspec(dllexport) void matcpy_c(const double *in,
    const int *nrow,
    const int *ncol,
    double *out);


    // matset

    // Set element in mat at row and col to val.
    // nrows is number of rows in mat. Shows row
    // and col reference in a C function.
    // REMEMBER: C row or col = Scilab row or col-1.

    void matset_c(double *mat,
    const int *nrows,
    const int *row,
    const int *col,
    double *val)
    {
    mat[*row - 1 + (*col - 1)*(*nrows)] = *val;
    }


    // matcpy

    // Function to copy one matrix to another.

    void matcpy_c(const double *in,
    const int *nrow,
    const int *ncol,
    double *out)
    {
    int row, col;

    for (col = 0; col < *ncol; col++) for (row = 0; row < *nrow; row++) out[row + col*(*nrow)] = in[row + col*(*nrow)]; }
  2. In Scilab, use link to load the DLL functions.

    link("path\filename.dll", "FunctionName", "c")

    The path is wherever you told VC++ to put your output. It is usually something like ProjectName\debug.

    Link uses the WindowsLoadLibrary function to load your DLL. See the VC++ on-line documentation for details.

  3. Use fort() to execute your function.

    Actually it is probably better to prepare a wrapper function to reduce the clutter of fort(). Here is a sample for the matset function above.

    // Wrapper function for calling C language routine matset_c from SciLab

    function mat = matset(mat, row, col, val)
    m = size(mat);
    mat = fort("matset_c",
    mat, 1, "d",
    m(1, 1), 2, "i",
    row, 3, "i",
    col, 4, "i",
    val, 5, "d",
    "out",
    m, 1, "d");
    endfunction

    A sample Scilab session is shown below:

    -->link("d:\vc\sci\debug\sci.dll", "matset_c", "c")
    Linking matset_c
    Link done
    ans =
    0.

    -->getf('E:\scilab\source\ctest.sci');
    -->mat = zeros(5, 5);
    -->matset(mat, 3, 3, 16.71)
    ans =
    ! 0. 0. 0. 0. 0. !
    ! 0. 0. 0. 0. 0. !
    ! 0. 0. 16.71 0. 0. !
    ! 0. 0. 0. 0. 0. !
    ! 0. 0. 0. 0. 0. !

Nessun commento: