Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Foadsf/3d73e4204a059fe836598d121bbae652 to your computer and use it in GitHub Desktop.
Save Foadsf/3d73e4204a059fe836598d121bbae652 to your computer and use it in GitHub Desktop.
Comparison of techniques (Gateway/addinter vs. link/call) for integrating Scilab with MinGW-w64 GCC compiled C/C++ code on Windows.

Comparison of Scilab-MinGW C/C++ Integration Methods

This Gist compares five different approaches demonstrated in various GitHub repositories for integrating C/C++ code with Scilab on Windows using the MinGW-w64 GCC compiler toolchain. The goal is to understand the trade-offs and identify potentially clean, concise, and canonical methods.

Repositories Analyzed:

  1. Foadsf/scilab-c-cpp-mingw-example
  2. Foadsf/scilab-mingw-c-gateway-mwe
  3. Foadsf/minimal-scilab-c-gateway
  4. Foadsf/scilab-mingw-module (Note: URL points to my_foo6, seems related)
  5. Foadsf/scilab-mingw-c-call-minimal-example

Common Challenge: Scilab's built-in ilib_build function (as of Scilab 2024.0.0) is primarily designed for MSVC on Windows and does not reliably support MinGW-w64 GCC out-of-the-box. This necessitates manual compilation steps (typically via batch scripts) in most examples.

Comparison Table

Feature scilab-c-cpp-mingw-example scilab-mingw-c-gateway-mwe minimal-scilab-c-gateway scilab-mingw-module (my_foo6) scilab-mingw-c-call-minimal-example
Core Method C Function + C++ Gateway (api_scilab) C Library + C++ Gateway (api_scilab) C Function + C++ Gateway (api_scilab) C Gateway Function + C++ Entry Point (api_scilab) Direct C Function Call (No Gateway)
Build Process Manual (.bat script, gcc/g++) Manual (.bat script, gcc/g++) Manual (.bat script, gcc/g++) Manual (.bat script, gcc/g++, uses ilib_gen_loader first) Manual (.bat script, gcc)
Scilab Integration exec('loader.sce') -> addinter (Static loader.sce) Direct addinter in test script Direct addinter in test script exec('loader.sce') -> addinter (Generated loader.sce) link() + call()
Complexity Moderate Moderate Moderate High (due to build complexity, stubs, many libs) Low
Requires C++ Gateway? Yes Yes Yes Yes (for the entry point build_lib) No
Dummy Headers Needed? Yes (sci_mem_alloc.h, gw_macros.h) Yes (sci_mem_alloc.h, gateway_c.h) Yes (sci_mem_alloc.h, gateway_c.h) Yes (sci_mem_alloc.h, gateway_c.h implied via build_lib.h -> c_gateway_prototype.h) No
Linker Stubs Needed? No (simple example) No (simple example) No (simple example) Yes (stubs.c for libintl_gettext) No
Key Files simple.c, gateway.cpp, loader.sce, build_and_run.bat minimal_lib.c, minimal_gateway.cpp, run_example.sce, build_and_run.bat simple_c_function.c, gateway.cpp, load_and_test.sce, build_and_run.bat sci_foo6.c, build_lib.cpp, stubs.c, generate_loader.sce, build_and_run.bat, test_foo6.sce simple_math.c/.h, run_example.sce, build_and_run.bat
Pros Clear README, Robust static loader, good troubleshooting notes. Clean separation of C lib/gateway, direct addinter. Similar to mwe, simple example. Attempts official toolbox structure, handles complex types (matrices). Simplest method, no C++ gateway, no Scilab API in C code, minimal linking dependencies for DLL.
Cons/Notes Manual build, requires dummy headers, -fpermissive used. Manual build, requires dummy headers. Manual build, requires dummy headers. ilib_build approach fails, complex manual build, requires linker stubs, links many Scilab libs. Requires specific C signature (pass-by-reference, _ suffix), call() syntax verbose.

Analysis and Recommendations

Based on the comparison, here's an analysis of the different approaches:

  1. link() / call() Method (scilab-mingw-c-call-minimal-example)

    • Simplicity: This is by far the simplest method. It avoids the Scilab C API (api_scilab) entirely within the C code, eliminates the need for a C++ gateway, and requires minimal linking. The build process is straightforward.
    • Constraints: It imposes strict requirements on the C function signature: Fortran-style naming (trailing underscore) and pass-by-reference for all arguments. The Scilab call() syntax is verbose and less intuitive than calling a normally registered function.
    • Best For: Very simple C functions (like basic math operations) where minimal integration effort is desired, and the constraints on the C signature and the verbose call() syntax are acceptable.
  2. Gateway (addinter) Methods (The other four examples)

    • Canonicity: Using a gateway function (sci_...) and registering it via addinter is the canonical Scilab way to integrate external code, especially for building toolboxes. It allows the C/C++ function to be called in Scilab just like any built-in function.
    • Flexibility: This approach is much more flexible in handling various Scilab data types (matrices, strings, lists, etc.) and allows for more complex logic within the gateway (argument checking, type conversion, memory management).
    • Complexity: Requires understanding the api_scilab, writing C++ gateway boilerplate, managing dummy headers (due to MinGW/Scilab distribution limitations), and handling a more complex manual build process involving linking against multiple Scilab libraries.
  3. Variations within Gateway Methods:

    • Build Process: All gateway examples require manual compilation scripts (.bat) because ilib_build fails with MinGW. The complexity varies (my_foo6 being the most complex due to more features and linker issues).
    • Loader (addinter Call):
      • Direct Call: scilab-mingw-c-gateway-mwe and minimal-scilab-c-gateway call addinter directly within the main test/usage script. This is simple for minimal examples.
      • Generated Loader: scilab-mingw-module (my_foo6) uses Scilab's ilib_gen_loader to create loader.sce. This aligns more closely with the standard toolbox build process but adds a Scilab execution step to the build.
      • Static Loader: scilab-c-cpp-mingw-example uses a handwritten, static loader.sce. This avoids the Scilab generation step and is robust, but requires manual updates if function names/DLL paths change.
    • Dummy Headers/Stubs: All gateway examples require dummy headers (sci_mem_alloc.h, gateway_c.h/gw_macros.h) to satisfy includes expected by Scilab's API headers when compiling standalone with MinGW. Complex examples like my_foo6 might also need linker stubs (stubs.c) to resolve symbols (like libintl_gettext) when linking MinGW-compiled code with Scilab's MSVC-built libraries.

Conclusion

  • For utmost simplicity and minimal C functions: The link() / call() method (scilab-mingw-c-call-minimal-example) is the most direct and requires the least effort, provided you adhere to its C function signature constraints and accept the verbose call() syntax in Scilab.
  • For standard Scilab integration, toolbox development, or handling complex data types: The Gateway (addinter) method is necessary. Given the ilib_build limitations with MinGW:
    • A manual build script (.bat) is unavoidable.
    • Dummy headers are required.
    • Among the gateway examples:
      • scilab-c-cpp-mingw-example offers a well-documented approach with a robust static loader, making it a good, practical starting point.
      • scilab-mingw-c-gateway-mwe demonstrates the slightly simpler direct addinter call, suitable if a separate loader script isn't desired for a simple project.
      • scilab-mingw-module (my_foo6) shows the complexities encountered when trying to replicate the full toolbox structure manually, including linker stubs, making it a valuable reference for troubleshooting but perhaps overly complex as a starting point.

Recommendation for Future Self / Others:

  1. If the C function is simple and can easily conform to the pass-by-reference/underscore suffix convention, start with scilab-mingw-c-call-minimal-example for its simplicity.
  2. Otherwise, for a more standard and flexible Scilab integration, use the gateway approach. scilab-c-cpp-mingw-example provides a practical and well-explained template for manual MinGW compilation with a robust static loader. Adapt its build script and gateway structure for your needs. Be prepared to manage dummy headers and potentially linker stubs for more complex dependencies.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment