One shared library carries any number of optimization models; each model
publishes what it is, what it instantiates from, and how to evaluate it —
objective, gradient, constraints, sparse Jacobian and Lagrangian Hessian —
behind plain C symbols, consumable from any language with a dlopen.
- cnlp.h — the specification. The header is the normative document (the sqlite3.h model — one artifact, nothing to drift from it): every contract lives in its comments, and its X-macros declare the full surface for a symbol prefix, so implementers get prototype checking against the same file they read.
The evaluation semantics are NLPModels.jl's, transliterated to C; the Lagrangian-Hessian convention (objective weight + multipliers, lower triangle) goes back to the AMPL Solver Library. The compiled-model-per-library idea is CUTEst's, here made size-parametric at runtime and multi-model; CppADCodeGen pioneered the in-library model catalogue this ABI's fixed-name symbols follow, and CasADi's codegen convention is the function-level cousin. FMI is the architectural analogue from simulation — shared library, typed description, instantiation, live parameters — with no NLP contract; this ABI is, structurally, FMI for NLPs. Solver C APIs (Ipopt, nlopt) define the same callbacks in the opposite direction — the consumer implements them for a solver — which is why a cnlp library binds directly to them. No standalone NLP ABI specification predates this one, to our knowledge.
example/ is the whole ABI in two small plain-C files:
qp.c, a complete size-parametric model library (~130
lines, including the catalogue tier), and solve.c, a
consumer that links against it — no dlopen, no tooling:
cc -shared -fPIC -O2 -o libqp.so qp.c
cc -O2 -o solve solve.c -L. -lqp -Wl,-rpath,'$ORIGIN' -lm && ./solveThe same libqp.so loads unchanged in the Julia and Python consumers.
Consumers: CNLPModels.jl
(Julia) and cnlpmodels-py
(Python, ctypes + numpy). Both carry tinyqp.c, a complete reference
implementation in plain C, and their test suites are the ABI's conformance
tests. The primary producer is
ExaModelsCompiler, which
compiles ExaModels model
recipes ahead of time — but the ABI is producer-neutral by design: anything
that can export these symbols is a model library.