#ifndef ARHIPLEX_INTERFACES_CPP_ARHIPLEX_CPP_H
#define ARHIPLEX_INTERFACES_CPP_ARHIPLEX_CPP_H

#include <stddef.h>

#include "arhiplex_cpp_exports.h"
#include "arhiplex_itf.h"

#define ARHIPLEX_DBL_TIMELIMIT "time_limit"
#define ARHIPLEX_DBL_RELGAP "mip_rel_gap" //


ARHIPLEX_CPP_EXPORT arhiplex::IModel *  CreateModel();
ARHIPLEX_CPP_EXPORT arhiplex::ISolveResult *  CreateSolveResult(const char* calc_uid, const char* name_mapping_file);
ARHIPLEX_CPP_EXPORT arhiplex::ILinearExpression * CreateLinearExpression();
ARHIPLEX_CPP_EXPORT arhiplex::IQuadExpression * CreateQuadExpression();
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(arhiplex::gen_expr_type);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(const arhiplex::ILinearExpression*);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(const arhiplex::IQuadExpression*);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(const arhiplex::IVariable*);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(double);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(arhiplex::gen_expr_type, const arhiplex::IGeneralExpression* operand);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralExpression * CreateGeneralExpression(arhiplex::gen_expr_type, const arhiplex::IGeneralExpression* left, const arhiplex::IGeneralExpression* right);
ARHIPLEX_CPP_EXPORT arhiplex::IGeneralConstraint * CreateGeneralConstraint(const arhiplex::IGeneralExpression*, const arhiplex::IVariable* var, const char*);
ARHIPLEX_CPP_EXPORT arhiplex::IConstraint * CreateConstraint(arhiplex::ILinearExpression*, arhiplex::constraint_sense, double);
ARHIPLEX_CPP_EXPORT arhiplex::IConstraint * CreateConstraint(arhiplex::IQuadExpression*, arhiplex::constraint_sense, double);

/* Model C interface */
extern "C" ARHIPLEX_CPP_EXPORT double Arhiplex_Inf();
extern "C" ARHIPLEX_CPP_EXPORT void* Model_Create();
extern "C" ARHIPLEX_CPP_EXPORT void Model_Read(void *model, const char *file_name);
extern "C" ARHIPLEX_CPP_EXPORT void Model_ReadMps(void *model, const char *file_name);
extern "C" ARHIPLEX_CPP_EXPORT void Model_ReadLp(void *model, const char *file_name);
extern "C" ARHIPLEX_CPP_EXPORT void Model_Write(void *model, const char *file_name, const char* name_mapping_file);
extern "C" ARHIPLEX_CPP_EXPORT void Model_WriteMps(void *model, const char *file_name, const char* name_mapping_file);
extern "C" ARHIPLEX_CPP_EXPORT void Model_WriteLp(void *model, const char *file_name, const char* name_mapping_file);
extern "C" ARHIPLEX_CPP_EXPORT int Model_GetIntParam(const void *model, const char* param_name);
extern "C" ARHIPLEX_CPP_EXPORT double Model_GetDblParam(const void *model, const char* param_name);
extern "C" ARHIPLEX_CPP_EXPORT const char* Model_GetStringParam(const void *model, const char* param_name) ;
extern "C" ARHIPLEX_CPP_EXPORT int Model_GetBoolParam(const void *model, const char* param_name) ;
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetIntParam(void *model, const char* param_name, int nVal);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetDblParam(void *model, const char* param_name, double dVal);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetStringParam(void *model, const char* param_name, const char* cVal);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetBoolParam(void *model, const char* param_name, int dVal);
extern "C" ARHIPLEX_CPP_EXPORT const char * Model_GetName(const void *model);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetName(void *model, const char * model_name);
extern "C" ARHIPLEX_CPP_EXPORT int Model_GetErrorCode(const void *model);
extern "C" ARHIPLEX_CPP_EXPORT const char* Model_GetErrorText(const void *model);
extern "C" ARHIPLEX_CPP_EXPORT void Model_Release(void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddVariable(void* model, double lb, double ub, double obj, arhiplex::variable_type var_type, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddConstraintLinear1(void* model, const void* expr, arhiplex::constraint_sense sense, double rhs, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddConstraintQuad1(void* model, const void* quad_expr, arhiplex::constraint_sense sense, double rhs, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddConstraintLinear2(void* model, const void* lin_exexpr, double lb, double ub, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddConstraintQuad2(void* model, const void* quad_expr, double lb, double ub, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddConstraint(void* model, const void* constr, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT int Model_GetVariablesCount(const void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetVariable(void* model, int var_idx);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetVariableByName(void* model, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT int Model_GetConstraintsCount(void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetConstraint(void* model, int constr_idx);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetConstraintByName(void* model, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetObjectiveSense(void* model, arhiplex::objective_sense sense);
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::objective_sense Model_GetObjectiveSense(const void* model);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetObjectiveOffset(void* model,double offset);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetObjectiveLinear(void* model, const void* expr, arhiplex::objective_sense sense);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetObjectiveQuad(void* model, const void* quad_expr, arhiplex::objective_sense sense);
extern "C" ARHIPLEX_CPP_EXPORT void Model_ClearObjective(void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetObjective(void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetQuadObjective(void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_Solve(const void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_SolveRemote(void* model, const char* name_mapping_file);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SolveRemoteAsync(void* model, const char* name_mapping_file);
extern "C" ARHIPLEX_CPP_EXPORT const char* Model_GetRemoteSolveLog(const void* model, const char* szCalcUID);
extern "C" ARHIPLEX_CPP_EXPORT void Model_RemoveVar(void* model, void* var);
extern "C" ARHIPLEX_CPP_EXPORT void Model_RemoveConstr(void* model, void* constr);
extern "C" ARHIPLEX_CPP_EXPORT void Model_Clear(void* model);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetLogFile(void* model, const char* log_file);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetLogCallback(void* model,  void* log_callback);
extern "C" ARHIPLEX_CPP_EXPORT void Model_AddMipStartValueByName(void* model, const char* var_name, double var_value);
extern "C" ARHIPLEX_CPP_EXPORT void Model_AddMipStartValue(void* model, const void* var, double var_value);
extern "C" ARHIPLEX_CPP_EXPORT void Model_AddMipStartValues(void* model, const char* sol_file);
extern "C" ARHIPLEX_CPP_EXPORT void Model_ClearMipStartValues(void* model);
extern "C" ARHIPLEX_CPP_EXPORT const char* Model_GetCalcUID(const void* model);
extern "C" ARHIPLEX_CPP_EXPORT int Model_IsMip(const void* model);
extern "C" ARHIPLEX_CPP_EXPORT int Model_IsNonlinear(const void* model);

/* Solve Result */
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::solve_result SolveResult_GetSolveResult(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::solution_status SolveResult_GetSolutionStatus(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetRelativeGap(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT unsigned int SolveResult_GetIterationsCount(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT std::int64_t SolveResult_GetProcessedNodesCount(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetObjectiveFunctionValue(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetBestBoundValue(const void* solve_res);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetSolveTime(const void* solve_res); // секунды
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetVariableValue(const void* solve_res, const void* var);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetVariableValueByName(const void* solve_res, const char* var_name);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetDualValue(const void* solve_res, const void* constr);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetDualValueByName(const void* solve_res, const char* constr_name);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetReducedCost(const void* solve_res, const void* var);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetReducedCostByName(const void* solve_res, const char* var_name);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetExpressionValueLinear(const void* solve_res, const void* expression);
extern "C" ARHIPLEX_CPP_EXPORT double SolveResult_GetExpressionValueQuad(const void* solve_res, const void* expression);
extern "C" ARHIPLEX_CPP_EXPORT void SolveResult_WriteSolution(const void* solve_res, const char* file_name);
extern "C" ARHIPLEX_CPP_EXPORT int SolveResult_GetErrorCode(const void *solve_res);
extern "C" ARHIPLEX_CPP_EXPORT const char* SolveResult_GetErrorText(const void *solve_res);
extern "C" ARHIPLEX_CPP_EXPORT void SolveResult_Release(void* solve_res);

/* Constraint */
extern "C" ARHIPLEX_CPP_EXPORT void* Constraint_CreateFromLinear(void* linear_expr, arhiplex::constraint_sense, double);
extern "C" ARHIPLEX_CPP_EXPORT void* Constraint_CreateFromQuad(void* quad_expr, arhiplex::constraint_sense, double);
extern "C" ARHIPLEX_CPP_EXPORT void Constraint_Remove(void* constr);
extern "C" ARHIPLEX_CPP_EXPORT const char * Constraint_GetName(const void *constr);
extern "C" ARHIPLEX_CPP_EXPORT void Constraint_SetName(void *constr, const char * constr_name);
extern "C" ARHIPLEX_CPP_EXPORT void* Constraint_GetLinearExpression(void *constr);
extern "C" ARHIPLEX_CPP_EXPORT void* Constraint_GetQuadExpression(void *constr);
extern "C" ARHIPLEX_CPP_EXPORT void Constraint_SetUpperBound(void *constr, double upper_bound);
extern "C" ARHIPLEX_CPP_EXPORT double Constraint_GetUpperBound(const void *constr);
extern "C" ARHIPLEX_CPP_EXPORT void Constraint_SetLowerBound(void *constr, double lower_bound);
extern "C" ARHIPLEX_CPP_EXPORT double Constraint_GetLowerBound(const void *constr);
extern "C" ARHIPLEX_CPP_EXPORT double Constraint_GetRange(const void *constr);
extern "C" ARHIPLEX_CPP_EXPORT void Constraint_SetRange(void *constr, double range);
extern "C" ARHIPLEX_CPP_EXPORT void Constraint_Release(void *constr);
extern "C" ARHIPLEX_CPP_EXPORT int Constraint_GetErrorCode(const void *constr);
extern "C" ARHIPLEX_CPP_EXPORT const char* Constraint_GetErrorText(const void *constr);

/* Variable */
extern "C" ARHIPLEX_CPP_EXPORT void Variable_Release(void *var);
extern "C" ARHIPLEX_CPP_EXPORT const char * Variable_GetName(const void *var);
extern "C" ARHIPLEX_CPP_EXPORT void Variable_SetName(void *var, const char * var_name);
extern "C" ARHIPLEX_CPP_EXPORT int Variable_GetErrorCode(const void *var);
extern "C" ARHIPLEX_CPP_EXPORT const char* Variable_GetErrorText(const void *var);
extern "C" ARHIPLEX_CPP_EXPORT void Variable_SetUpperBound(void *var, double upper_bound);
extern "C" ARHIPLEX_CPP_EXPORT double Variable_GetUpperBound(const void *var);
extern "C" ARHIPLEX_CPP_EXPORT void Variable_SetLowerBound(void *var, double lower_bound);
extern "C" ARHIPLEX_CPP_EXPORT double Variable_GetLowerBound(const void *var);
extern "C" ARHIPLEX_CPP_EXPORT void Variable_Remove(void *var);
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::variable_type Variable_GetType(const void *var);
extern "C" ARHIPLEX_CPP_EXPORT void Variable_SetType(void *var, arhiplex::variable_type type);

/* Quad Expression */
extern "C" ARHIPLEX_CPP_EXPORT void* QuadExpression_Create();
extern "C" ARHIPLEX_CPP_EXPORT void QuadExpression_Release(void *quad_expr);
extern "C" ARHIPLEX_CPP_EXPORT int QuadExpression_GetErrorCode(const void *quad_expr);
extern "C" ARHIPLEX_CPP_EXPORT const char* QuadExpression_GetErrorText(const void *quad_expr);
extern "C" ARHIPLEX_CPP_EXPORT int QuadExpression_GetTermsCount(const void* quad_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* QuadExpression_GetTermVariable1(const void* quad_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT int QuadExpression_GetTermVariable1Index(const void* quad_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT void* QuadExpression_GetTermVariable2(const void* quad_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT int QuadExpression_GetTermVariable2Index(const void* quad_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT double QuadExpression_GetTermCoeff(const void* quad_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT void QuadExpression_SetTermCoeff(void* quad_expr, int term_idx, double value);
extern "C" ARHIPLEX_CPP_EXPORT void QuadExpression_AddTerm(void* quad_expr, const void* pVar1, const void* pVar2, double coeff);
extern "C" ARHIPLEX_CPP_EXPORT void QuadExpression_AddExpression(void* quad_expr, const void* pExpr, double mult);
extern "C" ARHIPLEX_CPP_EXPORT void QuadExpression_RemoveTerm(void* quad_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT void* QuadExpression_GetLinearPart(void* quad_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* QuadExpression_CreateFreeCopy(const void* quad_expr);

/* Linear Expression */
extern "C" ARHIPLEX_CPP_EXPORT const char* LinearExpression_GetName(const void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_SetName(void *linear_expr, const char * expr_name);
extern "C" ARHIPLEX_CPP_EXPORT void* LinearExpression_Create();
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_Release(void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT int LinearExpression_GetErrorCode(const void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT const char* LinearExpression_GetErrorText(const void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT int LinearExpression_GetTermsCount(const void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* LinearExpression_GetTermVariable(const void *linear_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT int LinearExpression_GetTermVariableIndex(const void *linear_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT double LinearExpression_GetTermCoeff(const void *linear_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_SetTermCoeff(void *linear_expr, int term_idx, double value) ;
extern "C" ARHIPLEX_CPP_EXPORT double LinearExpression_GetConstant(const void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_SetConstant(void *linear_expr, double constant);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_AddConstant(void *linear_expr, double constant);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_AddTerm(void *linear_expr, const void *pVar, double coeff);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_AddExpression(void *linear_expr, const void *pExpr, double mult);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_RemoveTerm(void *linear_expr, int term_idx);
extern "C" ARHIPLEX_CPP_EXPORT void LinearExpression_RemoveVariable(void *linear_expr, const void* pVar);
extern "C" ARHIPLEX_CPP_EXPORT void* LinearExpression_GetQuadPart(void *linear_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* LinearExpression_CreateFreeCopy(const void *linear_expr);

/* Matrix model (same handle as Model_Create) */
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_AddVariables(
    void* model, size_t var_count,
    const double* lb, size_t lb_count,
    const double* ub, size_t ub_count,
    const double* obj, size_t obj_count,
    const arhiplex::variable_type* var_type, size_t var_type_count);
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_SetObjective(
    void* model,
    const double* quad_matrix, size_t rows, size_t cols,
    const double* obj, size_t obj_count,
    arhiplex::objective_sense sense);
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_SetObjectiveSparse(
    void* model,
    const double* quad_data, const int* indexes, const int* ind_ptr,
    size_t rows, size_t cols,
    const double* obj, size_t obj_count,
    arhiplex::objective_sense sense);
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_AddConstraint(
    void* model,
    const double* quad_matrix, size_t rows, size_t cols,
    const double* coefs, size_t coef_count,
    arhiplex::constraint_sense sense, double rhs);
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_AddConstraintSparse(
    void* model,
    const double* quad_data, const int* indexes, const int* ind_ptr,
    size_t rows, size_t cols,
    const double* coefs, size_t coef_count,
    arhiplex::constraint_sense sense, double rhs);
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_AddConstraintLinearSparse(
    void* model,
    const double* coefs, const int* coef_indexes, size_t var_count,
    arhiplex::constraint_sense sense, double rhs);
extern "C" ARHIPLEX_CPP_EXPORT void MatrixModel_AddConstraintsLinearSparse(
    void* model,
    const double* coefs, const int* coef_indexes, size_t var_count,
    const arhiplex::constraint_sense* senses, const double* rhs, size_t constraint_count);

/* Solve result bulk arrays and remote constructor */
extern "C" ARHIPLEX_CPP_EXPORT void* SolveResult_Create(const char* calc_uid, const char* name_mapping_file);
extern "C" ARHIPLEX_CPP_EXPORT const double* SolveResult_GetValuesArray(const void* solve_res, size_t* result_size);
extern "C" ARHIPLEX_CPP_EXPORT const double* SolveResult_GetDualValuesArray(const void* solve_res, size_t* result_size);
extern "C" ARHIPLEX_CPP_EXPORT const double* SolveResult_GetReducedCostsArray(const void* solve_res, size_t* result_size);

/* General expression */
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_Create(arhiplex::gen_expr_type type);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateFromLinear(const void* lin_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateFromQuad(const void* quad_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateFromVariable(const void* var);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateFromConstant(double constant);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateUnary(
    arhiplex::gen_expr_type type, const void* operand);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateBinary(
    arhiplex::gen_expr_type type, const void* left, const void* right);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralExpression_Release(void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT int GeneralExpression_GetErrorCode(const void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT const char* GeneralExpression_GetErrorText(const void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::gen_expr_type GeneralExpression_GetType(const void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT double GeneralExpression_GetConstant(const void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_GetVariable(void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT int GeneralExpression_GetExprCount(const void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT int GeneralExpression_GetArity(const void* gen_expr);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_GetExpr(const void* gen_expr, int idx);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralExpression_SetExpr(void* gen_expr, int idx, const void* child);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralExpression_AddExpr(void* gen_expr, const void* child);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralExpression_RemoveExpr(void* gen_expr, int idx);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralExpression_CreateFreeCopy(const void* gen_expr);

/* General constraint */
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralConstraint_Create(
    const void* expr, const void* var, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralConstraint_Release(void* constr);
extern "C" ARHIPLEX_CPP_EXPORT int GeneralConstraint_GetErrorCode(const void* constr);
extern "C" ARHIPLEX_CPP_EXPORT const char* GeneralConstraint_GetErrorText(const void* constr);
extern "C" ARHIPLEX_CPP_EXPORT const char* GeneralConstraint_GetName(const void* constr);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralConstraint_SetName(void* constr, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralConstraint_GetExpression(void* constr);
extern "C" ARHIPLEX_CPP_EXPORT void* GeneralConstraint_GetVariable(void* constr);
extern "C" ARHIPLEX_CPP_EXPORT void GeneralConstraint_Remove(void* constr);

/* Model general constraints and IIS */
extern "C" ARHIPLEX_CPP_EXPORT int Model_GetGeneralConstraintsCount(const void* model);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetGeneralConstraint(void* model, int idx);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_GetGeneralConstraintByName(void* model, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_AddGeneralConstraint(
    void* model, const void* expr, const void* var, const char* name);
extern "C" ARHIPLEX_CPP_EXPORT void Model_AddGeneralConstraintObject(void* model, const void* constr);
extern "C" ARHIPLEX_CPP_EXPORT void Model_RemoveGeneralConstraint(void* model, void* constr);
extern "C" ARHIPLEX_CPP_EXPORT void* Model_ComputeIis(const void* model);

extern "C" ARHIPLEX_CPP_EXPORT void ComputeIisResult_Release(void* result);
extern "C" ARHIPLEX_CPP_EXPORT int ComputeIisResult_GetErrorCode(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT const char* ComputeIisResult_GetErrorText(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::compute_iis_result ComputeIisResult_GetComputeIisResult(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT arhiplex::model_status ComputeIisResult_GetModelStatus(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT int ComputeIisResult_GetMinimal(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT int ComputeIisResult_GetNumConstraints(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT int ComputeIisResult_GetNumBounds(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT double ComputeIisResult_GetComputeIisTime(const void* result);
extern "C" ARHIPLEX_CPP_EXPORT void ComputeIisResult_WriteIis(const void* result, const char* file_name);

/* C function pointer log callback adapter for language bindings */
typedef void (*ArhiplexLogCallbackFn)(const char* msg, void* user_data);
extern "C" ARHIPLEX_CPP_EXPORT void Model_SetLogCallbackFn(
    void* model, ArhiplexLogCallbackFn callback, void* user_data);

#endif // ARHIPLEX_INTERFACES_CPP_ARHIPLEX_CPP_H