[FEA] Expand cuopt_c.h with problem-model accessors for non-Python language bindings
@akifcorduk is already working on this.
Since Aug 12, 2026.
- Dominant language
- Cuda
- Stars
- 1k
- Forks
- 233
- Avg merge
- 4d 4h
- Merged PRs (30d)
- 95
Description
Is your feature request related to a problem? Please describe.
The Java bindings (#1524) cannot reach parts of the problem model through the C API, so java/cuopt/src/main/native/cuopt_jni.cpp includes the private pdlp/cuopt_c_internal.hpp and reaches into problem_and_stream_view_t directly. There are 18 such call sites.
That couples libcuopt_jni.so to a specific libcuopt build rather than to a stable ABI. It is fine while the module is built from the same source tree, but it blocks shipping the jar as a binary artifact: a cuOpt point release can break it in ways no version range expresses. Any other C-ABI binding (Go, Rust, C#) would hit the same wall, and a jextract-based binding could not work around it at all, since jextract can only bind the C header.
This is the problem-model counterpart to #1202, which covers solver statistics.
Describe the solution you'd like
Roughly 10 functions. Two of them are already acknowledged as TODO in cuopt_c.h:
* TODO: there is no getter for the quadratic objective matrix (Q)
* or the quadratic constraint rows.
Name setters — the C API reads names but cannot set them
cuOptSetVariableNames(problem, const char* const* names, cuopt_int_t count)cuOptSetRowNames(problem, const char* const* names, cuopt_int_t count)cuOptSetProblemName(problem, const char* name)cuOptGetProblemName(problem, char* buf, cuopt_int_t size)— no getter exists either
Quadratic objective (Q is CSR, so this mirrors cuOptGetConstraintMatrix)
- a non-zero count attribute, plus
cuOptGetQuadraticObjective(problem, offsets, indices, values)
Quadratic constraint rows — the awkward one
quadratic_constraint_t is a variable-length array of variable-length records: each row carries a name, sense, RHS, a linear part (values + indices), and a COO Q (rows/cols/vals). Copy-out cannot express nested ragged data in one call, so it needs a shape-query-then-fill pattern, roughly:
cuOptGetNumQuadraticConstraints(problem, &n);
cuOptGetQuadraticConstraintSizes(problem, i, &n_linear, &n_quad);
cuOptGetQuadraticConstraint(problem, i, /* arrays */);
cuOptGetQuadraticConstraintName(problem, i, buf, size);
Describe alternatives you've considered
- Leave the bindings on private headers — current state. Works for a source build, blocks binary distribution.
- Return a struct — heavier ABI footprint, and does not solve the ragged quadratic-constraint case.
Additional context
- The copy-out accessors that cannot report "no data" were split out as #1706, since that is a behaviour bug rather than a missing accessor.
CUOPT_ATTR_PROBLEM_CATEGORYalready exists; that call site just needs rewiring and needs no new API.- Sizing, based on the seven functions already moved in #1524 (141 lines of implementation and 134 of header for 7): roughly 240 + 230 lines, plus tests. Everything except the quadratic-constraint accessors is mechanical.
- Suggested order: name setters and the problem-name getter first (trivial), then the quadratic objective getters (closes half the existing
TODO), then the quadratic constraint accessors once the shape-query pattern is agreed.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.