What are my options for wrapping a C-library (in my case Sundials) that uses CMake to build?
There seems to be alot floating around, c2nim, nimgen, nimterop etc.
What would be easiest to use for my use-case? :-)
Thank you, will take a closer look at it ;-)
I'm not very experienced in the C world but I think I want the entire library, so perhaps all headers in the include/ folder?
That's why I asked if you knew which headers you wanted to wrap. There's a whole bunch so targeting what you need would be a good start. Once you get one header with a few calls wrapped, built and linked, you can then add more as you go.
Use the dynlib option to link to the library.
You are so right ;-) I just went berserk and cImported stuff 😅 now I get something to compile at least. I think I will start with the nvector to see if I can get it to work :-) thank you very much.
I have a little wondering: There are lots of headers, some have dynamic libraries and some not. Should I cImport the ones with dynamic libraries and let recursion handle the rest or is it better to be on the safer side and cImport all headers?
Ok, got you :-)
I'm thinking of creating a proof of concept of the CVODE library at least so I'm checking what all the headers it needs #includes and cImports them as well.
Now that I have cImported some files, what would be the idiomatic way of creating a wrapper around it? Just exporting everything and importing it in wrapper.nim?
Do you have a repository? I've been trying to do the same exactly with the same library.
I started with nvector_serial. It is necessary to run first cmake in order to enable the creation of sundials_config.h.
As an example, what I got for that bit of library was:
# Resetting /home/jose/src/nimlang/sundials/build/project
{.passC: "-I/home/jose/src/nimlang/sundials/build/project/build/include".}
{.passC: "-I/home/jose/src/nimlang/sundials/build/project/include".}
{.passC: "-I/home/jose/src/nimlang/sundials/build/project/include/sundials".}
# Importing /home/jose/src/nimlang/sundials/build/project/include/nvector/nvector_serial.h
# Generated at 2019-07-03T00:18:52+02:00
# Command line:
# /home/jose/.nimble/pkgs/nimterop-0.1.0/nimterop/toast --pnim --preprocess --recurse --includeDirs+=/home/jose/src/nimlang/sundials/build/project/build/include --includeDirs+=/home/jose/src/nimlang/sundials/build/project/include --includeDirs+=/home/jose/src/nimlang/sundials/build/project/include/sundials --nim:/usr/bin/nim --pluginSourcePath=/tmp/nimterop_4019152023295567557.nim /home/jose/src/nimlang/sundials/build/project/include/nvector/nvector_serial.h
{.hint[ConvFromXtoItselfNotNeeded]: off.}
import nimterop/types
# -----------------------------------------------------------------
# * Implemented N_Vector types
# * -----------------------------------------------------------------
defineEnum(N_Vector_ID)
const
headernvector_serial {.used.} = "/home/jose/src/nimlang/sundials/build/project/include/nvector/nvector_serial.h"
# -----------------------------------------------------------------
# * Programmer(s): Scott D. Cohen, Alan C. Hindmarsh, Radu Serban,
# * and Aaron Collier @ LLNL
# * -----------------------------------------------------------------
# * SUNDIALS Copyright Start
# * Copyright (c) 2002-2019, Lawrence Livermore National Security
# * and Southern Methodist University.
# * All rights reserved.
# *
# * See the top-level LICENSE and NOTICE files for details.
# *
# * SPDX-License-Identifier: BSD-3-Clause
# * SUNDIALS Copyright End
# * -----------------------------------------------------------------
# * This is the header file for the serial implementation of the
# * NVECTOR module.
# *
# * Notes:
# *
# * - The definition of the generic N_Vector structure can be found
# * in the header file sundials_nvector.h.
# *
# * - The definition of the type 'realtype' can be found in the
# * header file sundials_types.h, and it may be changed (at the
# * configuration stage) according to the user's needs.
# * The sundials_types.h file also contains the definition
# * for the type 'booleantype'.
# *
# * - N_Vector arguments to arithmetic vector operations need not
# * be distinct. For example, the following call:
# *
# * N_VLinearSum_Serial(a,x,b,y,y);
# *
# * (which stores the result of the operation a*x+b*y in y)
# * is legal.
# * -----------------------------------------------------------------
# -----------------------------------------------------------------
# * Programmer(s): Radu Serban and Aaron Collier @ LLNL
# * -----------------------------------------------------------------
# * SUNDIALS Copyright Start
# * Copyright (c) 2002-2019, Lawrence Livermore National Security
# * and Southern Methodist University.
# * All rights reserved.
# *
# * See the top-level LICENSE and NOTICE files for details.
# *
# * SPDX-License-Identifier: BSD-3-Clause
# * SUNDIALS Copyright End
# * -----------------------------------------------------------------
# * This is the header file for a generic NVECTOR package.
# * It defines the N_Vector structure (_generic_N_Vector) which
# * contains the following fields:
# * - an implementation-dependent 'content' field which contains
# * the description and actual data of the vector
# * - an 'ops' filed which contains a structure listing operations
# * acting on such vectors
# * -----------------------------------------------------------------
# * This header file contains:
# * - enumeration constants for all SUNDIALS-defined vector types,
# * as well as a generic type for user-supplied vector types,
# * - type declarations for the _generic_N_Vector and
# * _generic_N_Vector_Ops structures, as well as references to
# * pointers to such structures (N_Vector), and
# * - prototypes for the vector functions which operate on
# * N_Vector objects.
# * -----------------------------------------------------------------
# * At a minimum, a particular implementation of an NVECTOR must
# * do the following:
# * - specify the 'content' field of N_Vector,
# * - implement the operations on those N_Vector objects,
# * - provide a constructor routine for new N_Vector objects
# *
# * Additionally, an NVECTOR implementation may provide the following:
# * - macros to access the underlying N_Vector data
# * - a constructor for an array of N_Vectors
# * - a constructor for an empty N_Vector (i.e., a new N_Vector with
# * a NULL data pointer).
# * - a routine to print the content of an N_Vector
# * -----------------------------------------------------------------
# -----------------------------------------------------------------
# * Programmer(s): Scott Cohen, Alan Hindmarsh, Radu Serban,
# * Aaron Collier, and Slaven Peles @ LLNL
# * -----------------------------------------------------------------
# * SUNDIALS Copyright Start
# * Copyright (c) 2002-2019, Lawrence Livermore National Security
# * and Southern Methodist University.
# * All rights reserved.
# *
# * See the top-level LICENSE and NOTICE files for details.
# *
# * SPDX-License-Identifier: BSD-3-Clause
# * SUNDIALS Copyright End
# * -----------------------------------------------------------------
# * This header file exports three types: realtype, sunindextype and
# * booleantype, as well as the constants SUNTRUE and SUNFALSE.
# *
# * Users should include the header file sundials_types.h in every
# * program file and use the exported name realtype instead of
# * float, double or long double.
# *
# * The constants SUNDIALS_SINGLE_PRECISION, SUNDIALS_DOUBLE_PRECISION
# * and SUNDIALS_LONG_DOUBLE_PRECISION indicate the underlying data
# * type of realtype.
# *
# * The legal types for realtype are float, double and long double.
# *
# * The constants SUNDIALS_INT64_T and SUNDIALS_INT32_T indicate
# * the underlying data type of sunindextype -- the integer data type
# * used for vector and matrix indices.
# *
# * Data types are set at the configuration stage.
# *
# * The macro RCONST gives the user a convenient way to define
# * real-valued literal constants. To use the constant 1.0, for example,
# * the user should write the following:
# *
# * #define ONE RCONST(1.0)
# *
# * If realtype is defined as a double, then RCONST(1.0) expands
# * to 1.0. If realtype is defined as a float, then RCONST(1.0)
# * expands to 1.0F. If realtype is defined as a long double,
# * then RCONST(1.0) expands to 1.0L. There is never a need to
# * explicitly cast 1.0 to (realtype). The macro can be used for
# * literal constants only. It cannot be used for expressions.
# * -----------------------------------------------------------------
# -----------------------------------------------------------------
# * Programmer(s): Aaron Collier and Radu Serban @ LLNL
# * -----------------------------------------------------------------
# * LLNS/SMU Copyright Start
# * Copyright (c) 2002-2018, Southern Methodist University and
# * Lawrence Livermore National Security
# *
# * This work was performed under the auspices of the U.S. Department
# * of Energy by Southern Methodist University and Lawrence Livermore
# * National Laboratory under Contract DE-AC52-07NA27344.
# * Produced at Southern Methodist University and the Lawrence
# * Livermore National Laboratory.
# *
# * All rights reserved.
# * For details, see the LICENSE file.
# * LLNS/SMU Copyright End
# * -----------------------------------------------------------------
# * SUNDIALS configuration header file
# * -----------------------------------------------------------------
# Define SUNDIALS version numbers
SUNDIALS_VERSION_MAJOR* = 5
SUNDIALS_VERSION_MINOR* = 0
SUNDIALS_VERSION_PATCH* = 0
# FCMIX: Define Fortran name-mangling macro for C identifiers.
# * Depending on the inferred scheme, one of the following six
# * macros will be defined:
# * #define SUNDIALS_F77_FUNC(name,NAME) name
# * #define SUNDIALS_F77_FUNC(name,NAME) name ## _
# * #define SUNDIALS_F77_FUNC(name,NAME) name ## __
# * #define SUNDIALS_F77_FUNC(name,NAME) NAME
# * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## _
# * #define SUNDIALS_F77_FUNC(name,NAME) NAME ## __
#
# FCMIX: Define Fortran name-mangling macro for C identifiers
# * which contain underscores.
#
# Define precision of SUNDIALS data type 'realtype'
# * Depending on the precision level, one of the following
# * three macros will be defined:
# * #define SUNDIALS_SINGLE_PRECISION 1
# * #define SUNDIALS_DOUBLE_PRECISION 1
# * #define SUNDIALS_EXTENDED_PRECISION 1
#
SUNDIALS_DOUBLE_PRECISION* = 1
# Define type of vector indices in SUNDIALS 'sunindextype'.
# * Depending on user choice of index type, one of the following
# * two macros will be defined:
# * #define SUNDIALS_INT64_T 1
# * #define SUNDIALS_INT32_T 1
#
SUNDIALS_INT64_T* = 1
# Define the type of vector indices in SUNDIALS 'sunindextype'.
# * The macro will be defined with a type of the appropriate size.
#
# Use generic math functions
# * If it was decided that generic math functions can be used, then
# * #define SUNDIALS_USE_GENERIC_MATH
#
# Use POSIX timers if available.
# * #define SUNDIALS_HAVE_POSIX_TIMERS
#
# Blas/Lapack available
# * If working libraries for Blas/lapack support were found, then
# * #define SUNDIALS_BLAS_LAPACK
#
# SUPERLUMT available
# * If working libraries for SUPERLUMT support were found, then
# * #define SUNDIALS_SUPERLUMT
#
# SUPERLUDIST available
# * If working libraries for SUPERLUDIST support were found, then
# * #define SUNDIALS_SUPERLUDIST
#
# KLU available
# * If working libraries for KLU support were found, then
# * #define SUNDIALS_KLU
#
# Trilinos available
# * If working libraries for Trilinos support were found, then
# * #define SUNDIALS_TRILINOS
#
# Trilinos with MPI is available, then
# * #define SUNDIALS_TRILINOS_HAVE_MPI
#
# Set if SUNDIALS is built with MPI support.
# *
#
# FNVECTOR: Allow user to specify different MPI communicator
# * If it was found that the MPI implementation supports MPI_Comm_f2c, then
# * #define SUNDIALS_MPI_COMM_F2C 1
# * otherwise
# * #define SUNDIALS_MPI_COMM_F2C 0
#
SUNDIALS_MPI_COMM_F2C* = 0
#
# *------------------------------------------------------------------
# * Type : booleantype
# *------------------------------------------------------------------
# * Constants : SUNFALSE and SUNTRUE
# *------------------------------------------------------------------
# * ANSI C does not have a built-in boolean data type. Below is the
# * definition for a new type called booleantype. The advantage of
# * using the name booleantype (instead of int) is an increase in
# * code readability. It also allows the programmer to make a
# * distinction between int and boolean data. Variables of type
# * booleantype are intended to have only the two values SUNFALSE and
# * SUNTRUE which are defined below to be equal to 0 and 1,
# * respectively.
# *------------------------------------------------------------------
#
SUNFALSE* = 0
SUNTRUE* = 1
SUNDIALS_NVEC_SERIAL* = 0.N_Vector_ID
SUNDIALS_NVEC_PARALLEL* = 1.N_Vector_ID
SUNDIALS_NVEC_OPENMP* = 2.N_Vector_ID
SUNDIALS_NVEC_PTHREADS* = 3.N_Vector_ID
SUNDIALS_NVEC_PARHYP* = 4.N_Vector_ID
SUNDIALS_NVEC_PETSC* = 5.N_Vector_ID
SUNDIALS_NVEC_CUDA* = 6.N_Vector_ID
SUNDIALS_NVEC_RAJA* = 7.N_Vector_ID
SUNDIALS_NVEC_OPENMPDEV* = 8.N_Vector_ID
SUNDIALS_NVEC_TRILINOS* = 9.N_Vector_ID
SUNDIALS_NVEC_MANYVECTOR* = 10.N_Vector_ID
SUNDIALS_NVEC_MPIMANYVECTOR* = 11.N_Vector_ID
SUNDIALS_NVEC_MPIPLUSX* = 12.N_Vector_ID
SUNDIALS_NVEC_CUSTOM* = 13.N_Vector_ID
{.pragma: impnvector_serial, importc, header: headernvector_serial.}
{.pragma: impnvector_serialC, impnvector_serial, cdecl.}
type
# Mark SUNDIALS API functions for export/import
# * When building shared SUNDIALS libraries under Windows, use
# * #define SUNDIALS_EXPORT __declspec(dllexport)
# * When linking to shared SUNDIALS libraries under Windows, use
# * #define SUNDIALS_EXPORT __declspec(dllimport)
# * In all other cases (other platforms or static libraries under
# * Windows), the SUNDIALS_EXPORT macro is empty
#
#
# *------------------------------------------------------------------
# * Macro _SUNDIALS_STRUCT_
# * The _SUNDIALS_STRUCT_ macro is defined as a `struct` unless
# * generating the SWIG interfaces - in that case it is defined as
# * nothing. This is needed to work around a bug in SWIG which prevents
# * it from properly parsing our generic module structures.
# *------------------------------------------------------------------
#
#
# *------------------------------------------------------------------
# * Type realtype
# * Macro RCONST
# * Constants BIG_REAL, SMALL_REAL, and UNIT_ROUNDOFF
# *------------------------------------------------------------------
#
realtype* {.impnvector_serial.} = cdouble
#
# *------------------------------------------------------------------
# * Type : sunindextype
# *------------------------------------------------------------------
# * Defines integer type to be used for vector and matrix indices.
# * User can build sundials to use 32- or 64-bit signed integers.
# * If compiler does not support portable data types, the SUNDIALS
# * CMake build system tries to find a type of the desired size.
# *------------------------------------------------------------------
#
sunindextype* {.impnvector_serial.} = int64
# -----------------------------------------------------------------
# * Generic definition of N_Vector
# * -----------------------------------------------------------------
# Forward reference for pointer to N_Vector_Ops object
N_Vector_Ops* {.impnvector_serial.} = ptr generic_N_Vector_Ops
# Forward reference for pointer to N_Vector object
N_Vector* {.impnvector_serial.} = ptr generic_N_Vector
# Define array of N_Vectors
N_Vector_S* {.impnvector_serial.} = ptr N_Vector
# Structure containing function pointers to vector operations
generic_N_Vector_Ops* {.importc: "struct _generic_N_Vector_Ops", header: headernvector_serial, bycopy.} = object
nvgetvectorid*: proc(a1: N_Vector): N_Vector_ID {.cdecl.}
nvclone*: proc(a1: N_Vector): N_Vector {.cdecl.}
nvcloneempty*: proc(a1: N_Vector): N_Vector {.cdecl.}
nvdestroy*: proc(a1: N_Vector) {.cdecl.}
nvspace*: proc(a1: N_Vector, a2: ptr sunindextype, a3: ptr sunindextype) {.cdecl.}
nvgetarraypointer*: proc(a1: N_Vector): ptr realtype {.cdecl.}
nvsetarraypointer*: proc(a1: ptr realtype, a2: N_Vector) {.cdecl.}
nvgetcommunicator*: proc(a1: N_Vector): pointer {.cdecl.}
nvgetlength*: proc(a1: N_Vector): sunindextype {.cdecl.}
nvlinearsum*: proc(a1: realtype, a2: N_Vector, a3: realtype, a4: N_Vector, a5: N_Vector) {.cdecl.}
nvconst*: proc(a1: realtype, a2: N_Vector) {.cdecl.}
nvprod*: proc(a1: N_Vector, a2: N_Vector, a3: N_Vector) {.cdecl.}
nvdiv*: proc(a1: N_Vector, a2: N_Vector, a3: N_Vector) {.cdecl.}
nvscale*: proc(a1: realtype, a2: N_Vector, a3: N_Vector) {.cdecl.}
nvabs*: proc(a1: N_Vector, a2: N_Vector) {.cdecl.}
nvinv*: proc(a1: N_Vector, a2: N_Vector) {.cdecl.}
nvaddconst*: proc(a1: N_Vector, a2: realtype, a3: N_Vector) {.cdecl.}
nvdotprod*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvmaxnorm*: proc(a1: N_Vector): realtype {.cdecl.}
nvwrmsnorm*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvwrmsnormmask*: proc(a1: N_Vector, a2: N_Vector, a3: N_Vector): realtype {.cdecl.}
nvmin*: proc(a1: N_Vector): realtype {.cdecl.}
nvwl2norm*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvl1norm*: proc(a1: N_Vector): realtype {.cdecl.}
nvcompare*: proc(a1: realtype, a2: N_Vector, a3: N_Vector) {.cdecl.}
nvinvtest*: proc(a1: N_Vector, a2: N_Vector): cint {.cdecl.}
nvconstrmask*: proc(a1: N_Vector, a2: N_Vector, a3: N_Vector): cint {.cdecl.}
nvminquotient*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvlinearcombination*: proc(a1: cint, a2: ptr realtype, a3: ptr N_Vector, a4: N_Vector): cint {.cdecl.}
nvscaleaddmulti*: proc(a1: cint, a2: ptr realtype, a3: N_Vector, a4: ptr N_Vector, a5: ptr N_Vector): cint {.cdecl.}
nvdotprodmulti*: proc(a1: cint, a2: N_Vector, a3: ptr N_Vector, a4: ptr realtype): cint {.cdecl.}
nvlinearsumvectorarray*: proc(a1: cint, a2: realtype, a3: ptr N_Vector, a4: realtype, a5: ptr N_Vector, a6: ptr N_Vector): cint {.cdecl.}
nvscalevectorarray*: proc(a1: cint, a2: ptr realtype, a3: ptr N_Vector, a4: ptr N_Vector): cint {.cdecl.}
nvconstvectorarray*: proc(a1: cint, a2: realtype, a3: ptr N_Vector): cint {.cdecl.}
nvwrmsnormvectorarray*: proc(a1: cint, a2: ptr N_Vector, a3: ptr N_Vector, a4: ptr realtype): cint {.cdecl.}
nvwrmsnormmaskvectorarray*: proc(a1: cint, a2: ptr N_Vector, a3: ptr N_Vector, a4: N_Vector, a5: ptr realtype): cint {.cdecl.}
nvscaleaddmultivectorarray*: proc(a1: cint, a2: cint, a3: ptr realtype, a4: ptr N_Vector, a5: ptr ptr N_Vector, a6: ptr ptr N_Vector): cint {.cdecl.}
nvlinearcombinationvectorarray*: proc(a1: cint, a2: cint, a3: ptr realtype, a4: ptr ptr N_Vector, a5: ptr N_Vector): cint {.cdecl.}
nvdotprodlocal*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvmaxnormlocal*: proc(a1: N_Vector): realtype {.cdecl.}
nvminlocal*: proc(a1: N_Vector): realtype {.cdecl.}
nvl1normlocal*: proc(a1: N_Vector): realtype {.cdecl.}
nvinvtestlocal*: proc(a1: N_Vector, a2: N_Vector): cint {.cdecl.}
nvconstrmasklocal*: proc(a1: N_Vector, a2: N_Vector, a3: N_Vector): cint {.cdecl.}
nvminquotientlocal*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvwsqrsumlocal*: proc(a1: N_Vector, a2: N_Vector): realtype {.cdecl.}
nvwsqrsummasklocal*: proc(a1: N_Vector, a2: N_Vector, a3: N_Vector): realtype {.cdecl.}
# A vector is a structure with an implementation-dependent
# 'content' field, and a pointer to a structure of vector
# operations corresponding to that implementation.
generic_N_Vector* {.importc: "struct _generic_N_Vector", header: headernvector_serial, bycopy.} = object
content*: pointer
ops*: N_Vector_Ops
#
# * -----------------------------------------------------------------
# * SERIAL implementation of N_Vector
# * -----------------------------------------------------------------
#
N_VectorContent_Serial* {.importc: "struct _N_VectorContent_Serial", header: headernvector_serial, bycopy.} = object
length*: sunindextype
own_data*: cint
data*: ptr realtype
# -----------------------------------------------------------------
# * Functions exported by NVECTOR module
# * -----------------------------------------------------------------
proc N_VNewEmpty*(): N_Vector {.impnvector_serialC.}
proc N_VFreeEmpty*(v: N_Vector) {.impnvector_serialC.}
proc N_VCopyOps*(w: N_Vector, v: N_Vector): cint {.impnvector_serialC.}
proc N_VGetVectorID*(w: N_Vector): N_Vector_ID {.impnvector_serialC.}
proc N_VClone*(w: N_Vector): N_Vector {.impnvector_serialC.}
proc N_VCloneEmpty*(w: N_Vector): N_Vector {.impnvector_serialC.}
proc N_VDestroy*(v: N_Vector) {.impnvector_serialC.}
proc N_VSpace*(v: N_Vector, lrw: ptr sunindextype, liw: ptr sunindextype) {.impnvector_serialC.}
proc N_VGetArrayPointer*(v: N_Vector): ptr realtype {.impnvector_serialC.}
proc N_VSetArrayPointer*(v_data: ptr realtype, v: N_Vector) {.impnvector_serialC.}
proc N_VGetCommunicator*(v: N_Vector): pointer {.impnvector_serialC.}
proc N_VGetLength*(v: N_Vector): sunindextype {.impnvector_serialC.}
# standard vector operations
proc N_VLinearSum*(a: realtype, x: N_Vector, b: realtype, y: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VConst*(c: realtype, z: N_Vector) {.impnvector_serialC.}
proc N_VProd*(x: N_Vector, y: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VDiv*(x: N_Vector, y: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VScale*(c: realtype, x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VAbs*(x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VInv*(x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VAddConst*(x: N_Vector, b: realtype, z: N_Vector) {.impnvector_serialC.}
proc N_VDotProd*(x: N_Vector, y: N_Vector): realtype {.impnvector_serialC.}
proc N_VMaxNorm*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VWrmsNorm*(x: N_Vector, w: N_Vector): realtype {.impnvector_serialC.}
proc N_VWrmsNormMask*(x: N_Vector, w: N_Vector, id: N_Vector): realtype {.impnvector_serialC.}
proc N_VMin*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VWL2Norm*(x: N_Vector, w: N_Vector): realtype {.impnvector_serialC.}
proc N_VL1Norm*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VCompare*(c: realtype, x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VInvTest*(x: N_Vector, z: N_Vector): cint {.impnvector_serialC.}
proc N_VConstrMask*(c: N_Vector, x: N_Vector, m: N_Vector): cint {.impnvector_serialC.}
proc N_VMinQuotient*(num: N_Vector, denom: N_Vector): realtype {.impnvector_serialC.}
# OPTIONAL fused vector operations
proc N_VLinearCombination*(nvec: cint, c: ptr realtype, X: ptr N_Vector, z: N_Vector): cint {.impnvector_serialC.}
proc N_VScaleAddMulti*(nvec: cint, a: ptr realtype, x: N_Vector, Y: ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VDotProdMulti*(nvec: cint, x: N_Vector, Y: ptr N_Vector, dotprods: ptr realtype): cint {.impnvector_serialC.}
# OPTIONAL vector array operations
proc N_VLinearSumVectorArray*(nvec: cint, a: realtype, X: ptr N_Vector, b: realtype, Y: ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VScaleVectorArray*(nvec: cint, c: ptr realtype, X: ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VConstVectorArray*(nvec: cint, c: realtype, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VWrmsNormVectorArray*(nvec: cint, X: ptr N_Vector, W: ptr N_Vector, nrm: ptr realtype): cint {.impnvector_serialC.}
proc N_VWrmsNormMaskVectorArray*(nvec: cint, X: ptr N_Vector, W: ptr N_Vector, id: N_Vector, nrm: ptr realtype): cint {.impnvector_serialC.}
proc N_VScaleAddMultiVectorArray*(nvec: cint, nsum: cint, a: ptr realtype, X: ptr N_Vector, Y: ptr ptr N_Vector, Z: ptr ptr N_Vector): cint {.impnvector_serialC.}
proc N_VLinearCombinationVectorArray*(nvec: cint, nsum: cint, c: ptr realtype, X: ptr ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
# OPTIONAL local reduction kernels (no parallel communication)
proc N_VDotProdLocal*(x: N_Vector, y: N_Vector): realtype {.impnvector_serialC.}
proc N_VMaxNormLocal*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VMinLocal*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VL1NormLocal*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VWSqrSumLocal*(x: N_Vector, w: N_Vector): realtype {.impnvector_serialC.}
proc N_VWSqrSumMaskLocal*(x: N_Vector, w: N_Vector, id: N_Vector): realtype {.impnvector_serialC.}
proc N_VInvTestLocal*(x: N_Vector, z: N_Vector): cint {.impnvector_serialC.}
proc N_VConstrMaskLocal*(c: N_Vector, x: N_Vector, m: N_Vector): cint {.impnvector_serialC.}
proc N_VMinQuotientLocal*(num: N_Vector, denom: N_Vector): realtype {.impnvector_serialC.}
# -----------------------------------------------------------------
# * Additional functions exported by NVECTOR module
# * -----------------------------------------------------------------
proc N_VCloneEmptyVectorArray*(count: cint, w: N_Vector): ptr N_Vector {.impnvector_serialC.}
proc N_VCloneVectorArray*(count: cint, w: N_Vector): ptr N_Vector {.impnvector_serialC.}
proc N_VDestroyVectorArray*(vs: ptr N_Vector, count: cint) {.impnvector_serialC.}
#
# * -----------------------------------------------------------------
# * Macros NV_CONTENT_S, NV_DATA_S, NV_OWN_DATA_S,
# * NV_LENGTH_S, and NV_Ith_S
# * -----------------------------------------------------------------
#
#
# * -----------------------------------------------------------------
# * Functions exported by nvector_serial
# * -----------------------------------------------------------------
#
proc N_VNew_Serial*(vec_length: sunindextype): N_Vector {.impnvector_serialC.}
proc N_VNewEmpty_Serial*(vec_length: sunindextype): N_Vector {.impnvector_serialC.}
proc N_VMake_Serial*(vec_length: sunindextype, v_data: ptr realtype): N_Vector {.impnvector_serialC.}
proc N_VCloneVectorArray_Serial*(count: cint, w: N_Vector): ptr N_Vector {.impnvector_serialC.}
proc N_VCloneVectorArrayEmpty_Serial*(count: cint, w: N_Vector): ptr N_Vector {.impnvector_serialC.}
proc N_VDestroyVectorArray_Serial*(vs: ptr N_Vector, count: cint) {.impnvector_serialC.}
proc N_VGetLength_Serial*(v: N_Vector): sunindextype {.impnvector_serialC.}
proc N_VPrint_Serial*(v: N_Vector) {.impnvector_serialC.}
proc N_VPrintFile_Serial*(v: N_Vector, outfile: ptr FILE) {.impnvector_serialC.}
proc N_VGetVectorID_Serial*(v: N_Vector): N_Vector_ID {.impnvector_serialC.}
proc N_VCloneEmpty_Serial*(w: N_Vector): N_Vector {.impnvector_serialC.}
proc N_VClone_Serial*(w: N_Vector): N_Vector {.impnvector_serialC.}
proc N_VDestroy_Serial*(v: N_Vector) {.impnvector_serialC.}
proc N_VSpace_Serial*(v: N_Vector, lrw: ptr sunindextype, liw: ptr sunindextype) {.impnvector_serialC.}
proc N_VGetArrayPointer_Serial*(v: N_Vector): ptr realtype {.impnvector_serialC.}
proc N_VSetArrayPointer_Serial*(v_data: ptr realtype, v: N_Vector) {.impnvector_serialC.}
# standard vector operations
proc N_VLinearSum_Serial*(a: realtype, x: N_Vector, b: realtype, y: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VConst_Serial*(c: realtype, z: N_Vector) {.impnvector_serialC.}
proc N_VProd_Serial*(x: N_Vector, y: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VDiv_Serial*(x: N_Vector, y: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VScale_Serial*(c: realtype, x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VAbs_Serial*(x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VInv_Serial*(x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VAddConst_Serial*(x: N_Vector, b: realtype, z: N_Vector) {.impnvector_serialC.}
proc N_VDotProd_Serial*(x: N_Vector, y: N_Vector): realtype {.impnvector_serialC.}
proc N_VMaxNorm_Serial*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VWrmsNorm_Serial*(x: N_Vector, w: N_Vector): realtype {.impnvector_serialC.}
proc N_VWrmsNormMask_Serial*(x: N_Vector, w: N_Vector, id: N_Vector): realtype {.impnvector_serialC.}
proc N_VMin_Serial*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VWL2Norm_Serial*(x: N_Vector, w: N_Vector): realtype {.impnvector_serialC.}
proc N_VL1Norm_Serial*(x: N_Vector): realtype {.impnvector_serialC.}
proc N_VCompare_Serial*(c: realtype, x: N_Vector, z: N_Vector) {.impnvector_serialC.}
proc N_VInvTest_Serial*(x: N_Vector, z: N_Vector): cint {.impnvector_serialC.}
proc N_VConstrMask_Serial*(c: N_Vector, x: N_Vector, m: N_Vector): cint {.impnvector_serialC.}
proc N_VMinQuotient_Serial*(num: N_Vector, denom: N_Vector): realtype {.impnvector_serialC.}
# fused vector operations
proc N_VLinearCombination_Serial*(nvec: cint, c: ptr realtype, V: ptr N_Vector, z: N_Vector): cint {.impnvector_serialC.}
proc N_VScaleAddMulti_Serial*(nvec: cint, a: ptr realtype, x: N_Vector, Y: ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VDotProdMulti_Serial*(nvec: cint, x: N_Vector, Y: ptr N_Vector, dotprods: ptr realtype): cint {.impnvector_serialC.}
# vector array operations
proc N_VLinearSumVectorArray_Serial*(nvec: cint, a: realtype, X: ptr N_Vector, b: realtype, Y: ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VScaleVectorArray_Serial*(nvec: cint, c: ptr realtype, X: ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VConstVectorArray_Serial*(nvecs: cint, c: realtype, Z: ptr N_Vector): cint {.impnvector_serialC.}
proc N_VWrmsNormVectorArray_Serial*(nvecs: cint, X: ptr N_Vector, W: ptr N_Vector, nrm: ptr realtype): cint {.impnvector_serialC.}
proc N_VWrmsNormMaskVectorArray_Serial*(nvecs: cint, X: ptr N_Vector, W: ptr N_Vector, id: N_Vector, nrm: ptr realtype): cint {.impnvector_serialC.}
proc N_VScaleAddMultiVectorArray_Serial*(nvec: cint, nsum: cint, a: ptr realtype, X: ptr N_Vector, Y: ptr ptr N_Vector, Z: ptr ptr N_Vector): cint {.impnvector_serialC.}
proc N_VLinearCombinationVectorArray_Serial*(nvec: cint, nsum: cint, c: ptr realtype, X: ptr ptr N_Vector, Z: ptr N_Vector): cint {.impnvector_serialC.}
# OPTIONAL local reduction kernels (no parallel communication)
proc N_VWSqrSumLocal_Serial*(x: N_Vector, w: N_Vector): realtype {.impnvector_serialC.}
proc N_VWSqrSumMaskLocal_Serial*(x: N_Vector, w: N_Vector, id: N_Vector): realtype {.impnvector_serialC.}
#
# * -----------------------------------------------------------------
# * Enable / disable fused vector operations
# * -----------------------------------------------------------------
#
proc N_VEnableFusedOps_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableLinearCombination_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableScaleAddMulti_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableDotProdMulti_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableLinearSumVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableScaleVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableConstVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableWrmsNormVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableWrmsNormMaskVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableScaleAddMultiVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
proc N_VEnableLinearCombinationVectorArray_Serial*(v: N_Vector, tf: cint): cint {.impnvector_serialC.}
This is so cool, we should definitely try to work together rather than making two separate versions ;-)
I have managed to wrap N_Vector_Serial and made it functional (don't know if it is memory safe and things like that though). And I have managed to compile some of the CVode functions thus far. What I havn't really figured out yet is how to run CMake from Nim so that it compiles correctly on windows/linux/mac. I had to do some hacking with the header files as Nimterop didn't want to #include some typedefs from nvector_serial.h so I put them in nvector_serial2.h for now. This is my code thus far, it still contains some low-level tests and unfinished stuff:
import os
import nimterop/[cimport, paths]
const srcDir = currentSourcePath().parentDir()
static:
cDebug()
cDisableCaching()
cIncludeDir(srcDir/"include")
cIncludeDir(srcDir/"lib")
cPlugin:
import strutils
proc onSymbol*(sym: var Symbol) {.exportc, dynlib.} =
if sym.kind == nskType:
if sym.name == "_N_VectorContent_Serial":
sym.name = "N_VectorContent_Serial_Base"
if sym.name == "ModifiedGS":
sym.name = "cModifiedGS"
if sym.name == "ClassicalGS":
sym.name = "cClassicalGS"
if sym.name == "_SpgmrMemRec":
sym.name = "c_SpgmrMemRec"
sym.name = sym.name.strip(chars = {'_'})
const
libsundials_nvecserial = srcDir/"lib/libsundials_nvecserial.dll"
libsundials_cvode = srcDir/"lib/libsundials_cvode.dll"
#[
cOverride:
type
sunindextype* = cint
realtype* = float
N_VectorContent_Serial*[I] {.importc: "struct _N_VectorContent_Serial", bycopy.} = object
length*: sunindextype
own_data*: cint
data*: ptr array[I, realtype]
]#
cImport(srcDir/"include/sundials/sundials_config.h")
cImport(srcDir/"include/sundials/sundials_types.h")
cImport(srcDir/"include/sundials/sundials_math.h")
cImport(srcDir/"include/sundials/sundials_nvector.h")
cImport(srcDir/"include/nvector/nvector_serial2.h")
cImport(srcDir/"include/nvector/nvector_serial.h", dynlib = "libsundials_nvecserial")
cImport(srcDir/"include/sundials/sundials_nonlinearsolver.h")
cImport(srcDir/"include/sundials/sundials_direct.h")
cImport(srcDir/"include/sundials/sundials_iterative.h")
cImport(srcDir/"include/sundials/sundials_matrix.h")
cImport(srcDir/"include/sundials/sundials_linearsolver.h")
cImport(srcDir/"include/cvode/cvode_ls.h")
cImport(srcDir/"include/cvode/cvode2.h")
cImport(srcDir/"include/cvode/cvode.h", dynlib="libsundials_cvode")
template ptr2Array[T](p: pointer): auto = cast[ptr UncheckedArray[T]](p)
template array2Ptr[T](arr: openArray[T]): auto = addr(arr[0])
template `->`(a, b: untyped): untyped =
a[].b
template NV_CONTENT_S(v: untyped): untyped = cast[N_VectorContent_Serial](v->content)
template NV_LENGTH_S(v: untyped): untyped = NV_CONTENT_S(v) -> length
template NV_OWN_DATA_S(v: untyped): untyped = NV_CONTENT_S(v) -> own_data
template NV_DATA_S(v: untyped): untyped = NV_CONTENT_S(v) -> data
template NV_Ith_S(v: untyped, i: sunindextype): untyped = ptr2Array[realtype](NV_DATA_S(v))[i]
type
NVectorType* = object
length*: int
rawVector*: ref[N_Vector]
proc newNVector*(length: int): NVectorType =
if length <= 0:
raise newException(ValueError, "NVector length must be greater than 0")
result.length = length
result.rawVector = new N_Vector
result.rawVector[] = N_VNew_Serial(result.length)
# create newNVector(length) and for over arr, NV_Ith_S(result, i) = arr[i] to keep it in memory.
proc newNVector*(arr: openArray[realtype]): NVectorType =
if arr.len <= 0:
raise newException(ValueError, "NVector length must be greater than 0")
result.length = arr.len
result.rawVector = new N_Vector
result.rawVector[] = N_VNew_Serial(result.length)
for i in 0 ..< result.length:
NV_Ith_S(result.rawVector[], i) = arr[i]
proc `[]`*(v: NVectorType, i: int): realtype =
if v.length <= i:
raise newException(ValueError, "index i is out of range. `[]`")
NV_Ith_S(v.rawVector[], i)
proc `$`*(v: NVectorType): string =
result = "NVector("
for i in 0 ..< v.length:
result = result & $v[i] & ", "
result = result & ")"
proc `==`*(a, b: NVectorType): bool =
let length = a.length
if length != b.length:
raise newException(ValueError, "NVectors must have same lengths for `==`")
let aData = ptr2Array[realtype](NV_DATA_S(a.rawVector[]))
let bData = ptr2Array[realtype](NV_DATA_S(b.rawVector[]))
for i in 0 ..< length:
if aData[i] != bData[i]:
return false
return true
proc `+`*(a, b: NVectorType): NVectorType =
if a.length != b.length:
raise newException(ValueError, "NVector must be of same length for addition")
result = newNVector(a.length)
N_VLinearSum_Serial(1.0, a.rawVector[], 1.0, b.rawVector[], result.rawVector[])
proc `+`*(v: NVectorType, c: realtype): NVectorType =
result = newNVector(v.length)
N_VAddConst_Serial(v.rawVector[], c, result.rawVector[])
proc `+`*(c: realtype, v: NVectorType): NVectorType =
result = newNVector(v.length)
N_VAddConst_Serial(v.rawVector[], c, result.rawVector[])
proc `+=`*(a: var NVectorType, b: NVectorType) =
if a.length != b.length:
raise newException(ValueError, "NVector must be of same length for addition")
N_VLinearSum_Serial(1.0, a.rawVector[], 1.0, b.rawVector[], a.rawVector[])
proc `+=`*(v: var NVectorType, c: realtype) =
N_VAddConst_Serial(v.rawVector[], c, v.rawVector[])
proc `-`*(a, b: NVectorType): NVectorType =
if a.length != b.length:
raise newException(ValueError, "NVector must be of same length for addition")
result = newNVector(a.length)
N_VLinearSum_Serial(1.0, a.rawVector[], -1.0, b.rawVector[], result.rawVector[])
proc `-`*(v: NVectorType, c: realtype): NVectorType =
result = newNVector(v.length)
N_VAddConst_Serial(v.rawVector[], -c, result.rawVector[])
# TODO
#[
proc `-`*(c: realtype, v: NVectorType): NVectorType =
result = newNVector(v.length)
N_VAddConst_Serial(v.rawVector[], c, result.rawVector[])
]#
proc `-=`*(a: var NVectorType, b: NVectorType) =
if a.length != b.length:
raise newException(ValueError, "NVector must be of same length for addition")
N_VLinearSum_Serial(1.0, a.rawVector[], -1.0, b.rawVector[], a.rawVector[])
proc `-=`*(v: var NVectorType, c: realtype) =
N_VAddConst_Serial(v.rawVector[], -c, v.rawVector[])
proc `*`*(v: NVectorType, c: realtype): NVectorType =
result = newNVector(v.length)
N_VScale_Serial(c, v.rawVector[], result.rawVector[])
proc `*`*(c: realtype, v: NVectorType): NVectorType =
result = newNVector(v.length)
N_VScale_Serial(c, v.rawVector[], result.rawVector[])
template CVodeProc*(name, body: untyped): untyped {.dirty.} =
proc `name`(t: realtype, y: N_Vector, ydot: N_Vector, user_data: pointer): cint {.cdecl.} =
discard
#[
proc newNVector1(arr: openArray[realtype]): NVectorType =
result.length = arr.len
result.rawVector = new N_Vector
result.rawVector[] = NV_Make_Serial(result.length, unsafeAddr(arr[0]))
]#
let a = N_VNew_Serial(3)
N_VPrint_Serial(a)
echo type(a)
echo type(a[])
echo type(a[].content)
echo type(a -> content)
#echo type(cast[ptr N_VectorContent_Serial](a->content))
echo type(NV_CONTENT_S(a)[])
echo type(NV_LENGTH_S(a))
echo type(NV_OWN_DATA_S(a))
echo type(NV_DATA_S(a))
#echo type(NV_Ith_S(a, 0))
var k: realtype = 4.0
let b = N_VMake_Serial(3, addr k)
N_VPrint_Serial(b)
let c = N_VNew_Serial(3)
N_VProd_Serial(a, b, c)
N_VPrint_Serial(c)
var y = N_VNew_Serial(3)
#var n = new N_VectorContent_Serial_Base
# manually create a N_VectorContent_Serial_Base
var j = NV_LENGTH_S(y)
echo type(j)
echo j.int
var m = ptr2Array[realtype](NV_DATA_S(y))
echo type(m)
echo m[0]
m[0] = 1.23
echo m[1]
echo m[2]
N_VPrint_Serial(y)
var arr: array[3, realtype] = [1.0, 2.5, 6.25]
NV_DATA_S(y) = array2Ptr[realtype](arr)
N_VPrint_Serial(y)
var h = NVectorType()
h.length = 3
h.rawVector = new N_Vector
h.rawVector[] = y
N_VPrint_Serial(h.rawVector[])
echo NV_Ith_S(h.rawVector[], 1)
NV_Ith_S(h.rawVector[], 1) = 7.8
echo NV_Ith_S(h.rawVector[], 1)
let d = newNVector(3)
N_VPrint_Serial(d.rawVector[])
let q = newNVector(@[2.3, 2.4, 2.5])
N_VPrint_Serial(q.rawVector[])
echo NV_Ith_S(q.rawVector[], 1)
NV_Ith_S(q.rawVector[], 1) = 6.20
N_VPrint_Serial(q.rawVector[])
echo "\n\n\n\nLet the real testing begin:"
echo "Addition:"
var v1 = newNVector([1.0, 2.0, 3.0])
var v2 = newNVector([4.0, 5.0, 6.0])
var vsum = v1 + v2
N_VPrint_Serial(vsum.rawVector[])
N_VPrint_Serial((1.0 + v1 + 1.0).rawVector[])
echo "Inplace Addition:"
v2 += v1
N_VPrint_Serial(v2.rawVector[])
v2 += 2.2
N_VPrint_Serial(v2.rawVector[])
echo v2 == v1
echo v2
echo v2[2]
echo -1.0 * v2
proc f(t: realtype, y: N_Vector, ydot: N_Vector, user_data: pointer): cint {.cdecl.} =
NV_Ith_S(ydot, 0) = NV_Ith_S(y, 0)
NV_Ith_S(ydot, 1) = NV_Ith_S(y, 1)
NV_Ith_S(ydot, 2) = NV_Ith_S(y, 3)
var cvode_mem: pointer = nil
cvode_mem = CVodeCreate(CV_ADAMS)
var t0 = 0.0
var y0 = newNVector([1.0, 1.0, 1.0])
let reltol = 1e-3
let abstol = 1e-3
var flag = CVodeInit(cvode_mem, f, t0, y0.rawVector[])
flag = CVodeSStolerances(cvode_mem, reltol, abstol)
I have managed to get a simple CVode program running. Hurray! :-)
proc f(t: realtype, y: N_Vector, ydot: N_Vector, user_data: pointer): cint {.cdecl.} =
NV_Ith_S(ydot, 0) = NV_Ith_S(y, 0)
NV_Ith_S(ydot, 1) = NV_Ith_S(y, 1)
NV_Ith_S(ydot, 2) = NV_Ith_S(y, 2)
var cvode_mem: pointer = nil
cvode_mem = CVodeCreate(CV_ADAMS)
var t0 = 0.0
var y0 = newNVector([1.0, 1.0, 1.0])
var A = SUNDenseMatrix(3, 3)
let reltol = 1e-8
let abstol = 1e-8
var flag = CVodeInit(cvode_mem, f, t0, y0.rawVector[])
flag = CVodeSStolerances(cvode_mem, reltol, abstol)
var LS = SUNLinSol_SPGMR(y0.rawVector[], 0, 0)
flag = CVodeSetLinearSolver(cvode_mem, LS, A)
var t: realtype = 0.0
var tout = 1.0
flag = CVode(cvode_mem, tout, y0.rawVector[], addr(t), CV_NORMAL)
import math
var correct = newNVector(@[exp(1.0), exp(1.0), exp(1.0)])
echo y0
echo "Error: ", correct - y0
CVodeFree(addr(cvode_mem))
flag = SUNLinSolFree(LS)
SUNMatDestroy(A)
I have uploaded it to Github: https://github.com/HugoGranstrom/nimsundials
Let me know if you get it to run :-)
I'd love to collaborate. But I am still pretty useless.
I am trying to use it on Linux.
Awesome to hear :-) I'm also new to this so we are in the same boat ;-) What we don't know, we can learn. And in our case, will learn 😄
Let me know if you gets it yo work, or more importantly if it doesn't. You learn more from a failure than a success 😉 I have just been pounding at some buttons and if it works from the beginning, I haven't really learned anything, I have just had some luck.
Awesome work!
Note that nimterop just added cmake support, makes it a little bit easier.
I am trying to help here wrapping Sundials. I have modified the original wrapper so that it downloads and build the library using cmake. You can find the code here.
As you can see, I hit a wall. When it compiles nim_sundials.nim.c I get:
home/jose/.cache/nim/nim_sundials_d/nim_sundials.nim.c:219:77: error: name of type ‘CVRhsFn’ unknown 219 | typedef N_CDECL_PTR(int, tyProc_dycob5keSi0v89cXsanNL9cA) (void* cvode_mem, CVRhsFn f, realtype t0, struct _generic_N_Vector* y0); | ^~~~~~~
I don't understand why it complains about CVRhsFn type being unknown. The file cvode/cvode.h defines:
typedef int (*CVRhsFn)(realtype t, N_Vector y,
N_Vector ydot, void *user_data);
And the wrapper is importing it:
cImport(installDirInclude/"cvode/cvode.h", dynlib="libsundials_cvode")
Any idea?