From ec4a7d6e0d60c3d6d05d2fed575de3e78495a436 Mon Sep 17 00:00:00 2001 From: Corentin Le Molgat Date: Fri, 18 Jan 2019 17:39:13 +0100 Subject: [PATCH] Rework C# Callback to use delegates --- makefiles/Makefile.dotnet.mk | 13 +- .../constraint_solver/csharp/SolverHelper.cs | 3 - .../csharp/constraint_solver.i | 588 +++++++----------- ortools/constraint_solver/csharp/routing.i | 91 ++- .../constraint_solver/csharp/routing_types.i | 18 - .../samples/SimpleRoutingProgram.cs | 18 +- ortools/constraint_solver/samples/Tsp.cs | 14 +- .../samples/TspDistanceMatrix.cs | 1 + ortools/util/csharp/functions.i | 51 -- ortools/util/functions_swig_helpers.h | 4 +- 10 files changed, 312 insertions(+), 489 deletions(-) delete mode 100644 ortools/util/csharp/functions.i diff --git a/makefiles/Makefile.dotnet.mk b/makefiles/Makefile.dotnet.mk index cf3baa488d..3c8170faa6 100644 --- a/makefiles/Makefile.dotnet.mk +++ b/makefiles/Makefile.dotnet.mk @@ -167,7 +167,6 @@ $(GEN_DIR)/ortools/constraint_solver/constraint_solver_csharp_wrap.cc: \ $(SRC_DIR)/ortools/constraint_solver/csharp/constraint_solver.i \ $(SRC_DIR)/ortools/base/base.i \ $(SRC_DIR)/ortools/util/csharp/proto.i \ - $(SRC_DIR)/ortools/util/csharp/functions.i \ $(CP_DEPS) \ | $(GEN_DIR)/ortools/constraint_solver $(SWIG_BINARY) $(SWIG_INC) -I$(INC_DIR) -c++ -csharp \ @@ -739,20 +738,20 @@ clean_dotnet: -$(DELREC) ortools$Sdotnet$SCreateSigningKey$Sbin -$(DELREC) ortools$Sdotnet$SCreateSigningKey$Sobj -$(DEL) $(DOTNET_ORTOOLS_SNK_PATH) - -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_NATIVE_ASSEMBLY_NAME)$S$(OR_TOOLS_NATIVE_ASSEMBLY_NAME).csproj + -$(DEL) ortools$Sdotnet$S$(OR_TOOLS_NATIVE_ASSEMBLY_NAME)$S$(OR_TOOLS_NATIVE_ASSEMBLY_NAME)*.csproj -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_NATIVE_ASSEMBLY_NAME)$Sbin -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_NATIVE_ASSEMBLY_NAME)$Sobj - -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_ASSEMBLY_NAME)$S$(OR_TOOLS_ASSEMBLY_NAME).csproj - -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_ASSEMBLY_NAME)$Sruntime.json + -$(DEL) ortools$Sdotnet$S$(OR_TOOLS_ASSEMBLY_NAME)$S$(OR_TOOLS_ASSEMBLY_NAME)*.csproj + -$(DEL) ortools$Sdotnet$S$(OR_TOOLS_ASSEMBLY_NAME)$Sruntime.json -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_ASSEMBLY_NAME)$Sbin -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_ASSEMBLY_NAME)$Sobj - -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_TESTS_ASSEMBLY_NAME)$S$(OR_TOOLS_TESTS_ASSEMBLY_NAME).csproj + -$(DEL) ortools$Sdotnet$S$(OR_TOOLS_TESTS_ASSEMBLY_NAME)$S$(OR_TOOLS_TESTS_ASSEMBLY_NAME)*.csproj -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_TESTS_ASSEMBLY_NAME)$Sbin -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_TESTS_ASSEMBLY_NAME)$Sobj - -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_ASSEMBLY_NAME)$S$(OR_TOOLS_FSHARP_ASSEMBLY_NAME).fsproj + -$(DEL) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_ASSEMBLY_NAME)$S$(OR_TOOLS_FSHARP_ASSEMBLY_NAME)*.fsproj -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_ASSEMBLY_NAME)$Sbin -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_ASSEMBLY_NAME)$Sobj - -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_TESTS_ASSEMBLY_NAME)$S$(OR_TOOLS_FSHARP_TESTS_ASSEMBLY_NAME).fsproj + -$(DEL) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_TESTS_ASSEMBLY_NAME)$S$(OR_TOOLS_FSHARP_TESTS_ASSEMBLY_NAME)*.fsproj -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_TESTS_ASSEMBLY_NAME)$Sbin -$(DELREC) ortools$Sdotnet$S$(OR_TOOLS_FSHARP_TESTS_ASSEMBLY_NAME)$Sobj -$(DELREC) $(PACKAGE_DIR) diff --git a/ortools/constraint_solver/csharp/SolverHelper.cs b/ortools/constraint_solver/csharp/SolverHelper.cs index 87fc0af371..d2ac15e88f 100644 --- a/ortools/constraint_solver/csharp/SolverHelper.cs +++ b/ortools/constraint_solver/csharp/SolverHelper.cs @@ -15,9 +15,6 @@ namespace Google.OrTools.ConstraintSolver { using System; using System.Collections.Generic; -public delegate long TransitCallback(long FromIndex, long ToIndex); -public delegate long UnaryTransitCallback(long FromIndex); - public partial class Solver : IDisposable { public IntVar[] MakeIntVarArray(int count, long min, long max) { IntVar[] array = new IntVar[count]; diff --git a/ortools/constraint_solver/csharp/constraint_solver.i b/ortools/constraint_solver/csharp/constraint_solver.i index d87c58fb41..3c6160dd3e 100644 --- a/ortools/constraint_solver/csharp/constraint_solver.i +++ b/ortools/constraint_solver/csharp/constraint_solver.i @@ -17,16 +17,18 @@ using System; using System.Runtime.InteropServices; using System.Collections; +using System.Collections.Generic; %} %include "enumsimple.swg" %include "stdint.i" %include "exception.i" %include "std_vector.i" +%include "std_common.i" +%include "std_string.i" %include "ortools/base/base.i" %include "ortools/util/csharp/tuple_set.i" -%include "ortools/util/csharp/functions.i" %include "ortools/util/csharp/proto.i" // We need to forward-declare the proto here, so that PROTO_INPUT involving it @@ -37,7 +39,7 @@ class ConstraintSolverParameters; class SearchLimitParameters; } // namespace operations_research -%module(directors="1", allprotected="1") operations_research; +%module(directors="1") operations_research; #pragma SWIG nowarn=473 %feature("director") BaseLns; @@ -81,8 +83,8 @@ struct FailureProtect { }; %} -typedef int64_t int64; -typedef uint64_t uint64; +//typedef int64_t int64; +//typedef uint64_t uint64; /* allow partial c# classes */ %typemap(csclassmodifiers) SWIGTYPE "public partial class" @@ -161,10 +163,6 @@ CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::LocalSearchOperator, LocalSearc CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::LocalSearchFilter, LocalSearchFilter) CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::SymmetryBreaker, SymmetryBreaker) -%ignore operations_research::Solver::MakeIntVarArray; -%ignore operations_research::Solver::MakeBoolVarArray; -%ignore operations_research::Solver::MakeFixedDurationIntervalVarArray; -%ignore operations_research::IntVarLocalSearchFilter::FindIndex; %ignore operations_research::PropagationBaseObject::set_action_on_fail; // Generic rename rule. @@ -198,11 +196,20 @@ CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::SymmetryBreaker, SymmetryBreake // Rename rule on SearchLimit %rename (IsCrossed) operations_research::SearchLimit::crossed; -// Rename rules on Solver. -%rename (Add) operations_research::Solver::AddConstraint; - // Rename rule on DisjunctiveConstraint. %rename (SequenceVar) operations_research::DisjunctiveConstraint::MakeSequenceVar; +// Keep reference to delegate to avoid GC to collect them early +%typemap(cscode) operations_research::DisjunctiveConstraint %{ + // Store list of delegates to avoid the GC to reclaim them. + private List indexEvaluator2Callbacks; + // Ensure that the GC does not collect any IndexEvaluator1Callback set from C# + // as the underlying C++ class will only store a pointer to it (i.e. no ownership). + private IndexEvaluator2 StoreIndexEvaluator2(IndexEvaluator2 c) { + if (indexEvaluator2Callbacks == null) indexEvaluator2Callbacks = new List(); + indexEvaluator2Callbacks.Add(c); + return c; + } +%} // Generic rename rules. %rename (ToString) *::DebugString; @@ -282,7 +289,7 @@ CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::SymmetryBreaker, SymmetryBreake %unignore operations_research::PathOperator::MakeNeighbor; // LocalSearchFilter -%feature("director") operations_research::IntVarLocalSearchFilter; +%feature("director") operations_research::LocalSearchFilter; %unignore operations_research::LocalSearchFilter::Accept; %unignore operations_research::LocalSearchFilter::Synchronize; %unignore operations_research::LocalSearchFilter::IsIncremental; @@ -293,6 +300,9 @@ CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::SymmetryBreaker, SymmetryBreake %feature("director") operations_research::IntVarLocalSearchFilter; %feature("nodirector") operations_research::IntVarLocalSearchFilter::Synchronize; // Inherited. %ignore operations_research::IntVarLocalSearchFilter::FindIndex; +%ignore operations_research::IntVarLocalSearchFilter::IntVarLocalSearchFilter( + const std::vector& vars, + Solver::ObjectiveWatcher objective_callback); %unignore operations_research::IntVarLocalSearchFilter::AddVars; // Inherited. %unignore operations_research::IntVarLocalSearchFilter::IsIncremental; %unignore operations_research::IntVarLocalSearchFilter::OnSynchronize; @@ -300,11 +310,25 @@ CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::SymmetryBreaker, SymmetryBreake %unignore operations_research::IntVarLocalSearchFilter::Start; %unignore operations_research::IntVarLocalSearchFilter::Value; %unignore operations_research::IntVarLocalSearchFilter::Var; // Inherited. - -// Rename NewSearch and EndSearch to add pinning. See the overrides of -// NewSearch in ../../open_source/csharp/constraint_solver/SolverHelper.cs -%rename (NewSearchAux) operations_research::Solver::NewSearch; -%rename (EndSearchAux) operations_research::Solver::EndSearch; +// Extend IntVarLocalSearchFilter with an intuitive API. +%extend operations_research::IntVarLocalSearchFilter { + int Index(IntVar* const var) { + int64 index = -1; + $self->FindIndex(var, &index); + return index; + } +} +// Keep reference to delegate to avoid GC to collect them early +%typemap(cscode) operations_research::IntVarLocalSearchFilter %{ + // Store list of delegates to avoid the GC to reclaim them. + private ObjectiveWatcher objectiveWatcherCallbacks; + // Ensure that the GC does not collect any IndexEvaluator1Callback set from C# + // as the underlying C++ class will only store a pointer to it (i.e. no ownership). + private ObjectiveWatcher StoreObjectiveWatcher(ObjectiveWatcher c) { + objectiveWatcherCallbacks = c; + return c; + } +%} // Transform IntVar. %ignore operations_research::IntVar::MakeDomainIterator; @@ -324,10 +348,14 @@ CS_TYPEMAP_STDVECTOR_OBJECT(operations_research::SymmetryBreaker, SymmetryBreake %typemap(csinterfaces_derived) operations_research::Constraint "IConstraintWithStatus"; +// Solver namespace operations_research { -// Take care of API with function. SWIG doesn't wrap std::function<> -// properly, so we write our custom wrappers for all methods involving -// std::function<>. +// Ignore rules on Solver. +%ignore Solver::MakeIntVarArray; +%ignore Solver::MakeBoolVarArray; +%ignore Solver::MakeFixedDurationIntervalVarArray; +// Take care of API with function. SWIG doesn't wrap std::function<> properly, +// so we write our custom wrappers for all methods involving std::function<>. %ignore Solver::MakeSearchLog( int branch_period, std::function display_callback); @@ -342,355 +370,168 @@ namespace operations_research { %ignore Solver::MakeActionDemon; %ignore Solver::MakeCustomLimit(std::function limiter); -%ignore Solver::MakeElement(IndexEvaluator1 values, IntVar* const index); -%ignore Solver::MakeMonotonicElement(IndexEvaluator1 values, bool increasing, - IntVar* const index); -%ignore Solver::MakeElement(IndexEvaluator2 values, IntVar* const index1, - IntVar* const index2); -%ignore Solver::MakePathCumul(const std::vector& nexts, - const std::vector& active, - const std::vector& cumuls, - IndexEvaluator2 transit_evaluator); -%ignore Solver::MakePathCumul(const std::vector& nexts, - const std::vector& active, - const std::vector& cumuls, - const std::vector& slacks, - IndexEvaluator2 transit_evaluator); -%ignore Solver::MakeNoCycle(const std::vector& nexts, - const std::vector& active, - IndexFilter1 sink_handler = nullptr); -%ignore Solver::MakeNoCycle(const std::vector& nexts, - const std::vector& active, - IndexFilter1 sink_handler, bool assume_paths); -%ignore Solver::MakeGuidedLocalSearch(bool maximize, IntVar* const objective, - IndexEvaluator2 objective_function, - int64 step, const std::vector& vars, - double penalty_factor); -%ignore Solver::MakeGuidedLocalSearch(bool maximize, IntVar* const objective, - IndexEvaluator3 objective_function, - int64 step, const std::vector& vars, - const std::vector& secondary_vars, - double penalty_factor); -%ignore Solver::MakePhase(const std::vector& vars, - IndexEvaluator1 var_evaluator, - IntValueStrategy val_str); -%ignore Solver::MakePhase(const std::vector& vars, - IntVarStrategy var_str, IndexEvaluator2 val_eval); - -%ignore Solver::MakePhase( - const std::vector& vars, IntVarStrategy var_str, - VariableValueComparator var_val1_val2_comparator); - -%ignore Solver::MakePhase(const std::vector& vars, - IndexEvaluator1 var_evaluator, - IndexEvaluator2 val_eval); - -%ignore Solver::MakePhase(const std::vector& vars, - IntVarStrategy var_str, IndexEvaluator2 val_eval, - IndexEvaluator1 tie_breaker); - -%ignore Solver::MakePhase(const std::vector& vars, - IndexEvaluator1 var_evaluator, - IndexEvaluator2 val_eval, - IndexEvaluator1 tie_breaker); -%ignore Solver::MakePhase(const std::vector& vars, - IndexEvaluator2 evaluator, EvaluatorStrategy str); -%ignore Solver::MakePhase(const std::vector& vars, - IndexEvaluator2 evaluator, - IndexEvaluator1 tie_breaker, - EvaluatorStrategy str); -%ignore Solver::MakeOperator(const std::vector& vars, - IndexEvaluator3 evaluator, - EvaluatorLocalSearchOperators op); -%ignore Solver::MakeOperator(const std::vector& vars, - const std::vector& secondary_vars, - IndexEvaluator3 evaluator, - EvaluatorLocalSearchOperators op); -%ignore Solver::MakeSumObjectiveFilter( - const std::vector& vars, IndexEvaluator2 values, - IntVar* const objective, Solver::LocalSearchFilterBound filter_enum); -%ignore Solver::MakeSumObjectiveFilter( - const std::vector& vars, IndexEvaluator2 values, - ObjectiveWatcher delta_objective_callback, IntVar* const objective, - Solver::LocalSearchFilterBound filter_enum); -%ignore Solver::MakeSumObjectiveFilter( - const std::vector& vars, const std::vector& secondary_vars, - Solver::IndexEvaluator3 values, IntVar* const objective, - Solver::LocalSearchFilterBound filter_enum); -%ignore Solver::MakeSumObjectiveFilter( - const std::vector& vars, const std::vector& secondary_vars, - Solver::IndexEvaluator3 values, ObjectiveWatcher delta_objective_callback, - IntVar* const objective, Solver::LocalSearchFilterBound filter_enum); %ignore Solver::ConcatenateOperators( const std::vector& ops, std::function evaluator); %ignore Solver::MakeClosureDemon(std::function closure); %ignore Solver::set_fail_intercept; +// Rename rules on Solver. +%rename (Add) Solver::AddConstraint; +// Rename NewSearch and EndSearch to add pinning. See the overrides of +// NewSearch in ../../open_source/csharp/constraint_solver/SolverHelper.cs +%rename (NewSearchAux) Solver::NewSearch; +%rename (EndSearchAux) Solver::EndSearch; + +// Define the delegate IndexEvaluator[1-3] callback types. +// This replace the IndexEvaluator[1-3] in the C# proxy class +%typemap(csimports) Solver %{ + using System.Collections.Generic; // List<> + + public delegate long IndexEvaluator1(long u); + public delegate long IndexEvaluator2(long u, long v); + public delegate long IndexEvaluator3(long u, long v, long w); + + public delegate bool IndexFilter1(long u); + public delegate void ObjectiveWatcher(long u); +%} + +// Keep reference to delegate to avoid GC to collect them early +%typemap(cscode) Solver %{ + // Store list of delegates to avoid the GC to reclaim them. + private List indexEvaluator1Callbacks; + private List indexEvaluator2Callbacks; + private List indexEvaluator3Callbacks; + + private List indexFilter1Callbacks; + private List objectiveWatcherCallbacks; + + // Ensure that the GC does not collect any IndexEvaluator1Callback set from C# + // as the underlying C++ class will only store a pointer to it (i.e. no ownership). + private IndexEvaluator1 StoreIndexEvaluator1(IndexEvaluator1 c) { + if (indexEvaluator1Callbacks == null) indexEvaluator1Callbacks = new List(); + indexEvaluator1Callbacks.Add(c); + return c; + } + private IndexEvaluator2 StoreIndexEvaluator2(IndexEvaluator2 c) { + if (indexEvaluator2Callbacks == null) indexEvaluator2Callbacks = new List(); + indexEvaluator2Callbacks.Add(c); + return c; + } + private IndexEvaluator3 StoreIndexEvaluator3(IndexEvaluator3 c) { + if (indexEvaluator3Callbacks == null) indexEvaluator3Callbacks = new List(); + indexEvaluator3Callbacks.Add(c); + return c; + } + + private IndexFilter1 StoreIndexFilter1(IndexFilter1 c) { + if (indexFilter1Callbacks == null) indexFilter1Callbacks = new List(); + indexFilter1Callbacks.Add(c); + return c; + } + private ObjectiveWatcher StoreObjectiveWatcher(ObjectiveWatcher c) { + if (objectiveWatcherCallbacks == null) objectiveWatcherCallbacks = new List(); + objectiveWatcherCallbacks.Add(c); + return c; + } +%} + +// Types in Foo.cs Foo::f(cstype csinput, ...) {Foo_f_SWIG(csin, ...);} +// e.g.: +// Foo::f(IndexEvaluator1 arg1) { +// ... +// ...PINVOKE.Foo_f_SWIG(..., StoreIndexEvaluator1(arg1), ...); +// } +%typemap(cstype, out="IntPtr") Solver::IndexEvaluator1 "IndexEvaluator1" +%typemap(csin) Solver::IndexEvaluator1 "StoreIndexEvaluator1($csinput)" +%typemap(cstype, out="IntPtr") Solver::IndexEvaluator2 "IndexEvaluator2" +%typemap(csin) Solver::IndexEvaluator2 "StoreIndexEvaluator2($csinput)" +%typemap(cstype, out="IntPtr") Solver::IndexEvaluator3 "IndexEvaluator3" +%typemap(csin) Solver::IndexEvaluator3 "StoreIndexEvaluator3($csinput)" + +%typemap(cstype, out="IntPtr") Solver::IndexFilter1 "IndexFilter1" +%typemap(csin) Solver::IndexFilter1 "StoreIndexFilter1($csinput)" +%typemap(cstype, out="IntPtr") Solver::ObjectiveWatcher "ObjectiveWatcher" +%typemap(csin) Solver::ObjectiveWatcher "StoreObjectiveWatcher($csinput)" +// Type in the prototype of PINVOKE function. +%typemap(imtype, out="IntPtr") Solver::IndexEvaluator1 "IndexEvaluator1" +%typemap(imtype, out="IntPtr") Solver::IndexEvaluator2 "IndexEvaluator2" +%typemap(imtype, out="IntPtr") Solver::IndexEvaluator3 "IndexEvaluator3" + +%typemap(imtype, out="IntPtr") Solver::IndexFilter1 "IndexFilter1" +%typemap(imtype, out="IntPtr") Solver::ObjectiveWatcher "ObjectiveWatcher" + +// Type use in module_csharp_wrap.h function declaration. +// since SWIG generate code as: `ctype argX` we can't use a C function pointer type. +%typemap(ctype) Solver::IndexEvaluator1 "void*" // "int64 (*)(int64)" +%typemap(ctype) Solver::IndexEvaluator2 "void*" // "int64 (*)(int64, int64)" +%typemap(ctype) Solver::IndexEvaluator3 "void*" // "int64 (*)(int64, int64, int64)" + +%typemap(ctype) Solver::IndexFilter1 "void*" // "bool (*)(int64)" +%typemap(ctype) Solver::ObjectiveWatcher "void*" // "void (*)(int64)" + +// Convert in module_csharp_wrap.cc input argument (delegate marshaled in C function pointer) to original std::function<...> +%typemap(in) Solver::IndexEvaluator1 %{ + $1 = [$input](int64 u) -> int64 { + return (*(int64 (*)(int64))$input)(u); + }; +%} +%typemap(in) Solver::IndexEvaluator2 %{ + $1 = [$input](int64 u, int64 v) -> int64 { + return (*(int64 (*)(int64, int64))$input)(u, v);}; +%} +%typemap(in) Solver::IndexEvaluator3 %{ + $1 = [$input](int64 u, int64 v, int64 w) -> int64 { + return (*(int64 (*)(int64, int64, int64))$input)(u, v, w);}; +%} + +%typemap(in) Solver::IndexFilter1 %{ + $1 = [$input](int64 u) -> bool { + return (*(bool (*)(int64))$input)(u);}; +%} +%typemap(in) Solver::ObjectiveWatcher %{ + $1 = [$input](int64 u) -> void { + return (*(void (*)(int64))$input)(u);}; +%} %extend Solver { - IntExpr* MakeElement(swig_util::LongToLong* values, IntVar* const index) { - return $self->MakeElement( - [values](int64 i) { return values->Run(i); }, index); - } - IntExpr* MakeMonotonicElement(swig_util::LongToLong* values, bool increasing, - IntVar* const index) { - return $self->MakeMonotonicElement( - [values](int64 i) { return values->Run(i); }, increasing, index); - } - IntExpr* MakeElement(swig_util::LongLongToLong* values, IntVar* const index1, - IntVar* const index2) { - return $self->MakeElement( - [values](int64 i, int64 j) { return values->Run(i, j); }, index1, - index2); - } - Constraint* MakePathCumul(const std::vector& nexts, - const std::vector& active, - const std::vector& cumuls, - swig_util::LongLongToLong* transit_evaluator) { - return $self->MakePathCumul( - nexts, active, cumuls, - [transit_evaluator](int64 i, int64 j) { - return transit_evaluator->Run(i, j); }); - } - Constraint* MakePathCumul(const std::vector& nexts, - const std::vector& active, - const std::vector& cumuls, - const std::vector& slacks, - swig_util::LongLongToLong* transit_evaluator) { - return $self->MakePathCumul(nexts, active, cumuls, slacks, - [transit_evaluator](int64 i, int64 j) { - return transit_evaluator->Run(i, j); }); - } - Constraint* MakeNoCycle(const std::vector& nexts, - const std::vector& active, - swig_util::LongToBoolean* sink_handler = nullptr) { - if (sink_handler == nullptr) { - return $self->MakeNoCycle(nexts, active, nullptr); - } else { - return $self->MakeNoCycle(nexts, active, - [sink_handler](int64 i) { - return sink_handler->Run(i); }); - } - } - Constraint* MakeNoCycle(const std::vector& nexts, - const std::vector& active, - swig_util::LongToBoolean* sink_handler, bool assume_paths) { - return $self->MakeNoCycle(nexts, active, - [sink_handler](int64 i) { - return sink_handler->Run(i); }); - } - SearchMonitor* MakeGuidedLocalSearch(bool maximize, IntVar* const objective, - swig_util::LongLongToLong* objective_function, - int64 step, const std::vector& vars, - double penalty_factor) { - return $self->MakeGuidedLocalSearch( - maximize, objective, - [objective_function](int64 i, int64 j) { - return objective_function->Run(i, j); }, - step, vars, penalty_factor); - } - SearchMonitor* MakeGuidedLocalSearch(bool maximize, IntVar* const objective, - swig_util::LongLongLongToLong* objective_function, - int64 step, const std::vector& vars, - const std::vector& secondary_vars, - double penalty_factor) { - return $self->MakeGuidedLocalSearch( - maximize, objective, - [objective_function](int64 i, int64 j, int64 k) { - return objective_function->Run(i, j, k); }, - step, vars, secondary_vars, penalty_factor); - } - DecisionBuilder* MakePhase(const std::vector& vars, - swig_util::LongToLong* var_evaluator, - IntValueStrategy val_str) { - return $self->MakePhase(vars, [var_evaluator](int64 i) { - return var_evaluator->Run(i); }, val_str); - } - DecisionBuilder* MakePhase(const std::vector& vars, - IntVarStrategy var_str, - swig_util::LongLongToLong* val_eval) { - operations_research::Solver::IndexEvaluator2 func = - [val_eval](int64 i, int64 j) { return val_eval->Run(i, j); }; - return $self->MakePhase(vars, var_str, func); - } - DecisionBuilder* MakePhase( - const std::vector& vars, IntVarStrategy var_str, - swig_util::LongLongLongToBoolean* var_val1_val2_comparator) { - operations_research::Solver::VariableValueComparator comp = - [var_val1_val2_comparator](int64 i, int64 j, int64 k) { - return var_val1_val2_comparator->Run(i, j, k); }; - return $self->MakePhase(vars, var_str, comp); - } - DecisionBuilder* MakePhase(const std::vector& vars, - swig_util::LongToLong* var_evaluator, - swig_util::LongLongToLong* val_eval) { - return $self->MakePhase(vars, [var_evaluator](int64 i) { return var_evaluator->Run(i); }, [val_eval](int64 i, int64 j) { return val_eval->Run(i, j); }); - } - DecisionBuilder* MakePhase(const std::vector& vars, - IntVarStrategy var_str, - swig_util::LongLongToLong* val_eval, - swig_util::LongToLong* tie_breaker) { - return $self->MakePhase( - vars, var_str, - [val_eval](int64 i, int64 j) { return val_eval->Run(i, j); }, - [tie_breaker](int64 i) { return tie_breaker->Run(i); }); - } - DecisionBuilder* MakePhase(const std::vector& vars, - swig_util::LongToLong* var_evaluator, - swig_util::LongLongToLong* val_eval, - swig_util::LongToLong* tie_breaker) { - return $self->MakePhase( - vars, - [var_evaluator](int64 i) { return var_evaluator->Run(i); }, - [val_eval](int64 i, int64 j) { return val_eval->Run(i, j); }, - [tie_breaker](int64 i) { return tie_breaker->Run(i); }); - } - DecisionBuilder* MakePhase(const std::vector& vars, - swig_util::LongLongToLong* evaluator, - EvaluatorStrategy str) { - return $self->MakePhase( - vars, - [evaluator](int64 i, int64 j) { return evaluator->Run(i, j); }, - str); - } - DecisionBuilder* MakePhase(const std::vector& vars, - swig_util::LongLongToLong* evaluator, - swig_util::LongToLong* tie_breaker, - EvaluatorStrategy str) { - return $self->MakePhase( - vars, - [evaluator](int64 i, int64 j) { return evaluator->Run(i, j); }, - [tie_breaker](int64 i) { return tie_breaker->Run(i); }, str); - } - LocalSearchOperator* MakeOperator(const std::vector& vars, - swig_util::LongLongLongToLong* evaluator, - EvaluatorLocalSearchOperators op) { - return $self->MakeOperator( - vars, - [evaluator](int64 i, int64 j, int64 k) { - return evaluator->Run(i, j, k); }, op); - } - LocalSearchOperator* MakeOperator(const std::vector& vars, - const std::vector& secondary_vars, - swig_util::LongLongLongToLong* evaluator, - EvaluatorLocalSearchOperators op) { - return $self->MakeOperator( - vars, secondary_vars, - [evaluator](int64 i, int64 j, int64 k) { - return evaluator->Run(i, j, k); }, op); - } - LocalSearchFilter* MakeSumObjectiveFilter( - const std::vector& vars, swig_util::LongLongToLong* values, - IntVar* const objective, Solver::LocalSearchFilterBound filter_enum) { - return $self->MakeSumObjectiveFilter( - vars, [values](int64 i, int64 j) { return values->Run(i, j); }, - objective, filter_enum); - } - LocalSearchFilter* MakeSumObjectiveFilter( - const std::vector& vars, swig_util::LongLongToLong* values, - swig_util::LongToVoid* delta_objective_callback, IntVar* const objective, - Solver::LocalSearchFilterBound filter_enum) { - return $self->MakeSumObjectiveFilter( - vars, [values](int64 i, int64 j) { return values->Run(i, j); }, - [delta_objective_callback](int64 i) { - return delta_objective_callback->Run(i); }, - objective, filter_enum); - } - LocalSearchFilter* MakeSumObjectiveFilter( - const std::vector& vars, const std::vector& secondary_vars, - swig_util::LongLongLongToLong* values, IntVar* const objective, - Solver::LocalSearchFilterBound filter_enum) { - return $self->MakeSumObjectiveFilter( - vars, secondary_vars, - [values](int64 i, int64 j, int64 k) { return values->Run(i, j, k); }, - objective, filter_enum); - } - LocalSearchFilter* MakeSumObjectiveFilter( - const std::vector& vars, - const std::vector& secondary_vars, - swig_util::LongLongLongToLong* values, - swig_util::LongToVoid* delta_objective_callback, - IntVar* const objective, Solver::LocalSearchFilterBound filter_enum) { - return $self->MakeSumObjectiveFilter( - vars, secondary_vars, - [values](int64 i, int64 j, int64 k) { return values->Run(i, j, k); }, - [delta_objective_callback](int64 i) { - return delta_objective_callback->Run(i); }, - objective, filter_enum); - } - LocalSearchOperator* ConcatenateOperators( - const std::vector& ops, - swig_util::IntIntToLong* evaluator) { - return $self->ConcatenateOperators(ops, [evaluator](int i, int64 j) { - return evaluator->Run(i, j); }); - } - SearchMonitor* MakeSearchLog( - int branch_count, - OptimizeVar* const objective, - swig_util::VoidToString* display_callback) { - return $self->MakeSearchLog(branch_count, objective, [display_callback]() { - return display_callback->Run(); - }); - } - SearchMonitor* MakeSearchLog( - int branch_count, - IntVar* const obj_var, - swig_util::VoidToString* display_callback) { - return $self->MakeSearchLog(branch_count, obj_var, [display_callback]() { - return display_callback->Run(); - }); - } - SearchMonitor* MakeSearchLog( - int branch_count, - swig_util::VoidToString* display_callback) { - return $self->MakeSearchLog(branch_count, [display_callback]() { - return display_callback->Run(); - }); - } - SearchLimit* MakeCustomLimit(swig_util::VoidToBoolean* limiter) { - return $self->MakeCustomLimit([limiter]() { return limiter->Run(); }); - } - Demon* MakeClosureDemon(swig_util::VoidToVoid* closure) { - return $self->MakeClosureDemon([closure]() { return closure->Run(); }); - } + //LocalSearchOperator* ConcatenateOperators( + // const std::vector& ops, + // swig_util::IntIntToLong* evaluator) { + // return $self->ConcatenateOperators(ops, [evaluator](int i, int64 j) { + // return evaluator->Run(i, j); }); + //} + //SearchMonitor* MakeSearchLog( + // int branch_count, + // OptimizeVar* const objective, + // swig_util::VoidToString* display_callback) { + // return $self->MakeSearchLog(branch_count, objective, [display_callback]() { + // return display_callback->Run(); + // }); + //} + //SearchMonitor* MakeSearchLog( + // int branch_count, + // IntVar* const obj_var, + // swig_util::VoidToString* display_callback) { + // return $self->MakeSearchLog(branch_count, obj_var, [display_callback]() { + // return display_callback->Run(); + // }); + //} + //SearchMonitor* MakeSearchLog( + // int branch_count, + // swig_util::VoidToString* display_callback) { + // return $self->MakeSearchLog(branch_count, [display_callback]() { + // return display_callback->Run(); + // }); + //} + //SearchLimit* MakeCustomLimit(swig_util::VoidToBoolean* limiter) { + // return $self->MakeCustomLimit([limiter]() { return limiter->Run(); }); + //} + //Demon* MakeClosureDemon(swig_util::VoidToVoid* closure) { + // return $self->MakeClosureDemon([closure]() { return closure->Run(); }); + //} } // extend Solver -%ignore DisjunctiveConstraint::SetTransitionTime(Solver::IndexEvaluator2 transit_evaluator); -%extend DisjunctiveConstraint { - void SetTransitionTime(swig_util::LongLongToLong* transit_evaluator) { - $self->SetTransitionTime([transit_evaluator](int64 i, int64 j) { return transit_evaluator->Run(i, j); }); - } -} // extend DisjunctiveConstraint - -%ignore Pack::AddWeightedSumLessOrEqualConstantDimension( - Solver::IndexEvaluator1 weights, const std::vector& bounds); -%ignore Pack::AddWeightedSumLessOrEqualConstantDimension( - Solver::IndexEvaluator2 weights, const std::vector& bounds); -%ignore Pack::AddWeightedSumEqualVarDimension(Solver::IndexEvaluator2 weights, - const std::vector& loads); -%extend Pack { -void AddWeightedSumLessOrEqualConstantDimension( - swig_util::LongToLong* weights, const std::vector& bounds) { - operations_research::Solver::IndexEvaluator1 eval = [weights](int64 i) { - return weights->Run(i); - }; - return $self->AddWeightedSumLessOrEqualConstantDimension(eval, bounds); -} - -void AddWeightedSumLessOrEqualConstantDimension( - swig_util::LongLongToLong* weights, const std::vector& bounds) { - operations_research::Solver::IndexEvaluator2 eval = - [weights](int64 i, int64 j) { return weights->Run(i, j); }; - return $self->AddWeightedSumLessOrEqualConstantDimension(eval, bounds); -} -void AddWeightedSumEqualVarDimension( - swig_util::LongLongToLong* weights, const std::vector& loads) { - return $self->AddWeightedSumEqualVarDimension([weights](int64 i, int64 j) { return weights->Run(i, j); }, loads); -} - -} // extend Pack - // No custom wrapping for this method, we simply ignore it. %ignore SearchLog::SearchLog( Solver* const s, OptimizeVar* const obj, IntVar* const var, @@ -844,19 +685,32 @@ void AddWeightedSumEqualVarDimension( } } -%extend IntVarLocalSearchFilter { - int Index(IntVar* const var) { - int64 index = -1; - $self->FindIndex(var, &index); - return index; - } -} - class LocalSearchPhaseParameters { public: LocalSearchPhaseParameters(); ~LocalSearchPhaseParameters(); }; + +// Pack +// Keep reference to delegate to avoid GC to collect them early +%typemap(cscode) Pack %{ + // Store list of delegates to avoid the GC to reclaim them. + private List indexEvaluator1Callbacks; + private List indexEvaluator2Callbacks; + // Ensure that the GC does not collect any IndexEvaluator1Callback set from C# + // as the underlying C++ class will only store a pointer to it (i.e. no ownership). + private IndexEvaluator1 StoreIndexEvaluator1(IndexEvaluator1 c) { + if (indexEvaluator1Callbacks == null) indexEvaluator1Callbacks = new List(); + indexEvaluator1Callbacks.Add(c); + return c; + } + private IndexEvaluator2 StoreIndexEvaluator2(IndexEvaluator2 c) { + if (indexEvaluator2Callbacks == null) indexEvaluator2Callbacks = new List(); + indexEvaluator2Callbacks.Add(c); + return c; + } +%} + } // namespace operations_research // Protobuf support diff --git a/ortools/constraint_solver/csharp/routing.i b/ortools/constraint_solver/csharp/routing.i index 0f6dee83c4..f14a58bdac 100644 --- a/ortools/constraint_solver/csharp/routing.i +++ b/ortools/constraint_solver/csharp/routing.i @@ -15,7 +15,6 @@ %include "ortools/constraint_solver/csharp/constraint_solver.i" %include "ortools/constraint_solver/csharp/routing_types.i" %include "ortools/constraint_solver/csharp/routing_index_manager.i" -%include "ortools/util/csharp/functions.i" // We need to forward-declare the proto here, so that PROTO_INPUT involving it // works correctly. The order matters very much: this declaration needs to be @@ -51,22 +50,7 @@ class RoutingSearchParameters; %ignore operations_research::RoutingModel::MakeStateDependentTransit; %ignore operations_research::RoutingModel::AddDimensionDependentDimensionWithVehicleCapacity; -%ignore operations_research::RoutingModel::RegisterTransitCallback( - operations_research::TransitCallback2); -%ignore operations_research::RoutingModel::RegisterUnaryTransitCallback( - operations_research::TransitCallback1); - %extend operations_research::RoutingModel { - int RegisterTransitCallback(swig_util::LongLongToLong* callback) { - return $self->RegisterTransitCallback([callback](int64 i, int64 j) { - return callback->Run(i, j); - }); - } - int RegisterUnaryTransitCallback(swig_util::LongToLong* callback) { - return $self->RegisterUnaryTransitCallback([callback](int64 i) { - return callback->Run(i); - }); - } void AddVectorDimension(const std::vector& values, int64 capacity, bool fix_start_cumul_to_zero, @@ -75,19 +59,72 @@ class RoutingSearchParameters; self->AddVectorDimension(values.data(), capacity, fix_start_cumul_to_zero, name); } - - int RegisterTransitCallback(operations_research::TransitCallback c) { - return $self->RegisterTransitCallback([c](int64 i, int64 j) { - return (*c)(i, j); - }); - } - int RegisterUnaryTransitCallback(operations_research::UnaryTransitCallback c) { - return $self->RegisterUnaryTransitCallback([c](int64 i) { - return (*c)(i); - }); - } } +// RoutingModel +namespace operations_research { +// Define the delegate for Transit callback types. +// This replace the RoutingTransitCallback[1-2] in the C# proxy class +%typemap(csimports) RoutingModel %{ + using System.Collections.Generic; // List<> + + public delegate long UnaryTransitCallback(long fromIndex); + public delegate long TransitCallback(long fromIndex, long toIndex); +%} + +// Keep reference to delegate to avoid GC to collect them early +%typemap(cscode) RoutingModel %{ + // Store list of delegate to avoid the GC to reclaim them. + private List unaryTransitCallbacks; + private List transitCallbacks; + private IndexEvaluator2 indexEvaluator2Callback; + + // Ensure that the GC does not collect any TransitCallback set from C# + // as the underlying C++ class stores a shallow copy + private UnaryTransitCallback StoreUnaryTransitCallback(UnaryTransitCallback c) { + if (unaryTransitCallbacks == null) unaryTransitCallbacks = new List(); + unaryTransitCallbacks.Add(c); + return c; + } + private TransitCallback StoreTransitCallback(TransitCallback c) { + if (transitCallbacks == null) transitCallbacks = new List(); + transitCallbacks.Add(c); + return c; + } + // only use in RoutingModel::SetFirstSolutionEvaluator() + private IndexEvaluator2 StoreIndexEvaluator2(IndexEvaluator2 c) { + indexEvaluator2Callback = c; + return c; + } +%} + +// Types in Proxy class (foo.cs) e.g.: +// Foo::f(cstype $csinput, ...) {Foo_f_SWIG(csin, ...);} +%typemap(cstype, out="IntPtr") RoutingTransitCallback1 "UnaryTransitCallback" +%typemap(csin) RoutingTransitCallback1 "StoreUnaryTransitCallback($csinput)" +%typemap(cstype, out="IntPtr") RoutingTransitCallback2 "TransitCallback" +%typemap(csin) RoutingTransitCallback2 "StoreTransitCallback($csinput)" +// Type in the prototype of PINVOKE function. +%typemap(imtype, out="IntPtr") RoutingTransitCallback1 "UnaryTransitCallback" +%typemap(imtype, out="IntPtr") RoutingTransitCallback2 "TransitCallback" + +// Type use in module_csharp_wrap.h function declaration. +// since SWIG generate code as: `ctype argX` we can't use a C function pointer type. +%typemap(ctype) RoutingTransitCallback1 "void*" // "int64 (*)(int64)" +%typemap(ctype) RoutingTransitCallback2 "void*" // "int64 (*)(int64, int64)" + +// Convert in module_csharp_wrap.cc input argument (delegate marshaled in C function pointer) to original std::function<...> +%typemap(in) RoutingTransitCallback1 %{ + $1 = [$input](int64 fromIndex) -> int64 { + return (*(int64 (*)(int64))$input)(fromIndex); + }; +%} +%typemap(in) RoutingTransitCallback2 %{ + $1 = [$input](int64 fromIndex, int64 toIndex) -> int64 { + return (*(int64 (*)(int64, int64))$input)(fromIndex, toIndex);}; +%} +} // namespace operations_research + // Add PickupAndDeliveryPolicy enum value to RoutingModel (like RoutingModel::Status) // For C++11 strongly typed enum SWIG support see https://github.com/swig/swig/issues/316 %extend operations_research::RoutingModel { diff --git a/ortools/constraint_solver/csharp/routing_types.i b/ortools/constraint_solver/csharp/routing_types.i index 8f2f9f6bbb..af0e2ae985 100644 --- a/ortools/constraint_solver/csharp/routing_types.i +++ b/ortools/constraint_solver/csharp/routing_types.i @@ -77,21 +77,3 @@ DEFINE_INDEX_TYPE(operations_research::RoutingDisjunctionIndex); DEFINE_INDEX_TYPE(operations_research::RoutingVehicleClassIndex); %include "ortools/constraint_solver/routing_types.h" - -%{ -namespace operations_research { - typedef int64 (*TransitCallback)(int64, int64); - typedef int64 (*UnaryTransitCallback)(int64); -} // namespace operations_research -%} - -%define %DEFINE_CALLBACK(TYPE, CSTYPE) - %typemap(ctype) TYPE, TYPE& "void*" - %typemap(in) TYPE %{ $1 = (TYPE)$input; %} - %typemap(in) TYPE& %{ $1 = (TYPE*)&$input; %} - %typemap(imtype, out="IntPtr") TYPE, TYPE& "CSTYPE" - %typemap(cstype, out="IntPtr") TYPE, TYPE& "CSTYPE" - %typemap(csin) TYPE, TYPE& "$csinput" -%enddef -%DEFINE_CALLBACK(operations_research::TransitCallback, TransitCallback) -%DEFINE_CALLBACK(operations_research::UnaryTransitCallback, UnaryTransitCallback) diff --git a/ortools/constraint_solver/samples/SimpleRoutingProgram.cs b/ortools/constraint_solver/samples/SimpleRoutingProgram.cs index c1d26e6bfd..e45be5f072 100644 --- a/ortools/constraint_solver/samples/SimpleRoutingProgram.cs +++ b/ortools/constraint_solver/samples/SimpleRoutingProgram.cs @@ -42,15 +42,19 @@ public class SimpleRoutingProgram { RoutingModel routing = new RoutingModel(manager); // [END routing_model] - // Define cost of each arc. - // [START arc_cost] + // Create a distance callback. + // [START distance_callback] int transitCallbackIndex = routing.RegisterTransitCallback( (long fromIndex, long toIndex) => { - // Convert from routing variable Index to distance matrix NodeIndex. - var fromNode = manager.IndexToNode(fromIndex); - var toNode = manager.IndexToNode(toIndex); - return Math.Abs(toNode - fromNode); } - ); + // Convert from routing variable Index to distance matrix NodeIndex. + var fromNode = manager.IndexToNode(fromIndex); + var toNode = manager.IndexToNode(toIndex); + return Math.Abs(toNode - fromNode); + }); + // [END distance_callback] + + // Define cost of each arc. + // [START arc_cost] routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); // [END arc_cost] diff --git a/ortools/constraint_solver/samples/Tsp.cs b/ortools/constraint_solver/samples/Tsp.cs index 5ba99fcb83..7551b22e3c 100644 --- a/ortools/constraint_solver/samples/Tsp.cs +++ b/ortools/constraint_solver/samples/Tsp.cs @@ -59,7 +59,7 @@ public class Tsp { /// positions and computes the Manhattan distance between the two /// positions of two different indices. /// - class ManhattanDistance : LongLongToLong { + class ManhattanDistance { public ManhattanDistance( in DataModel data, in RoutingIndexManager manager) { @@ -82,7 +82,7 @@ public class Tsp { /// /// Returns the manhattan distance between the two nodes /// - public override long Run(long FromIndex, long ToIndex) { + public long call(long FromIndex, long ToIndex) { // Convert from routing variable Index to distance matrix NodeIndex. int FromNode = indexManager_.IndexToNode(FromIndex); int ToNode = indexManager_.IndexToNode(ToIndex); @@ -136,12 +136,14 @@ public class Tsp { RoutingModel routing = new RoutingModel(manager); // [END routing_model] + // Create a distance callback. + // [START distance_callback] + var distanceCallback = new ManhattanDistance(data, manager); + int transitCallbackIndex = routing.RegisterTransitCallback(distanceCallback.call); + // [END distance_callback] + // Define cost of each arc. // [START arc_cost] - LongLongToLong distanceEvaluator = new ManhattanDistance(data, manager); - //protect callbacks from the GC - GC.KeepAlive(distanceEvaluator); - int transitCallbackIndex = routing.RegisterTransitCallback(distanceEvaluator); routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); // [END arc_cost] diff --git a/ortools/constraint_solver/samples/TspDistanceMatrix.cs b/ortools/constraint_solver/samples/TspDistanceMatrix.cs index 0ad819773d..478f5e44de 100644 --- a/ortools/constraint_solver/samples/TspDistanceMatrix.cs +++ b/ortools/constraint_solver/samples/TspDistanceMatrix.cs @@ -107,6 +107,7 @@ public class TspDistanceMatrix { return data.GetDistanceMatrix()[fromNode, toNode]; } ); routing.SetArcCostEvaluatorOfAllVehicles(transitCallbackIndex); + GC.Collect(); // [END arc_cost] // Setting first solution heuristic. diff --git a/ortools/util/csharp/functions.i b/ortools/util/csharp/functions.i deleted file mode 100644 index cd6e9a6938..0000000000 --- a/ortools/util/csharp/functions.i +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2010-2018 Google LLC -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This file provides swig wrapping for some specialization of std::function -// parameters. Currently, swig does not support much of C++11 features, and -// especially not the std::function. - -// C# callers will need to use a specific "type" of callbacks: they must -// specialize one of the existing generic callback classes defined in -// ../functions_swig_helpers.h (which are SWIG-wrapped to C# in a -// straightforward way). See the examples. - -%include "ortools/base/base.i" - -%include "std_common.i" -%include "std_string.i" - -%{ -#include -#include "ortools/base/integral_types.h" -#include "ortools/util/functions_swig_helpers.h" -%} - -%module(directors="1") operations_research_swig_util - -// --------- Include the swig helpers file to create the director classes ------ -// We cannot use %ignoreall/%unignoreall as this is not compatible with nested -// swig files. - -%feature("director") operations_research::swig_util::LongToLong; -%feature("director") operations_research::swig_util::LongLongToLong; -%feature("director") operations_research::swig_util::IntIntToLong; -%feature("director") operations_research::swig_util::IntToLong; -%feature("director") operations_research::swig_util::LongLongLongToLong; -%feature("director") operations_research::swig_util::LongToBoolean; -%feature("director") operations_research::swig_util::VoidToString; -%feature("director") operations_research::swig_util::VoidToBoolean; -%feature("director") operations_research::swig_util::LongLongLongToBoolean; -%feature("director") operations_research::swig_util::LongToVoid; - -%include "ortools/util/functions_swig_helpers.h" diff --git a/ortools/util/functions_swig_helpers.h b/ortools/util/functions_swig_helpers.h index a1cb1d8ee9..0d81d3e686 100644 --- a/ortools/util/functions_swig_helpers.h +++ b/ortools/util/functions_swig_helpers.h @@ -15,9 +15,7 @@ #define OR_TOOLS_UTIL_FUNCTIONS_SWIG_HELPERS_H_ // This file contains class definitions for the wrapping of C++ std::functions -// in Java and C#. It is #included by java/functions.i and -// csharp/functions.i. - +// in Java. It is #included by java/functions.i #include #include