1- #include " pyoptinterface/dylib.hpp"
2- #include " pyoptinterface/solver_common.hpp"
31#include " pyoptinterface/gurobi_model.hpp"
4- #include < fmt/core.h>
2+ #include " fmt/core.h"
53
6- namespace gurobi
4+ extern " C "
75{
8- #define B (f ) decltype (&::f) f = nullptr
6+ int __stdcall GRBloadenvinternal (GRBenv **envP, const char *logfilename, int major, int minor,
7+ int tech);
8+ int __stdcall GRBemptyenvinternal (GRBenv **envP, int major, int minor, int tech);
9+ int __stdcall GRBloadenv_1200 (GRBenv **envP, const char *logfile);
10+ int __stdcall GRBemptyenv_1200 (GRBenv **envP);
11+ }
912
13+ namespace gurobi
14+ {
15+ #define B DYLIB_DECLARE
1016APILIST
11-
1217#undef B
1318
19+ // Gurobi 12.0.0 workarounds
20+ DYLIB_DECLARE (GRBloadenvinternal);
21+ DYLIB_DECLARE (GRBemptyenvinternal);
22+
1423static DynamicLibrary lib;
1524static bool is_loaded = false ;
1625
@@ -27,25 +36,73 @@ bool load_library(const std::string &path)
2736 return false ;
2837 }
2938
30- #define B (f ) \
31- { \
32- auto ptr = reinterpret_cast <decltype (f)>(lib.get_symbol (#f)); \
33- if (ptr == nullptr ) \
34- { \
35- fmt::print (" function {} is not loaded correctly" , #f); \
36- return false ; \
37- } \
38- f = ptr; \
39- }
39+ DYLIB_LOAD_INIT;
40+
41+ #define B DYLIB_LOAD_FUNCTION
4042 APILIST
4143#undef B
4244
43- is_loaded = true ;
45+ // We have to deal with Gurobi 12.0.0 where some functions are absent from the dynamic library
46+ {
47+ int major, minor, techinical;
48+ auto GRBversion_p =
49+ reinterpret_cast <decltype (GRBversion)>(_function_pointers[" GRBversion" ]);
50+ if (GRBversion_p != nullptr )
51+ {
52+ GRBversion_p (&major, &minor, &techinical);
53+
54+ if (major == 12 && minor == 0 && techinical == 0 )
55+ {
56+ DYLIB_LOAD_FUNCTION (GRBloadenvinternal);
57+ DYLIB_LOAD_FUNCTION (GRBemptyenvinternal);
58+ _function_pointers[" GRBloadenv" ] = &GRBloadenv_1200;
59+ _function_pointers[" GRBemptyenv" ] = &GRBemptyenv_1200;
60+
61+ // Now check there is no nullptr in _function_pointers
62+ _load_success = true ;
63+ for (auto &pair : _function_pointers)
64+ {
65+ if (pair.second == nullptr )
66+ {
67+ fmt::print (" function {} is not loaded correctly\n " , pair.first );
68+ _load_success = false ;
69+ }
70+ }
71+
72+ if (_load_success)
73+ {
74+ DYLIB_SAVE_FUNCTION (GRBloadenvinternal);
75+ DYLIB_SAVE_FUNCTION (GRBemptyenvinternal);
76+ }
77+ }
78+ }
79+ }
4480
45- return true ;
81+ if (IS_DYLIB_LOAD_SUCCESS)
82+ {
83+ #define B DYLIB_SAVE_FUNCTION
84+ APILIST
85+ #undef B
86+ is_loaded = true ;
87+ return true ;
88+ }
89+ else
90+ {
91+ return false ;
92+ }
4693}
4794} // namespace gurobi
4895
96+ int GRBloadenv_1200 (GRBenv **envP, const char *logfile)
97+ {
98+ return gurobi::GRBloadenvinternal (envP, logfile, 12 , 0 , 0 );
99+ }
100+
101+ int GRBemptyenv_1200 (GRBenv **envP)
102+ {
103+ return gurobi::GRBemptyenvinternal (envP, 12 , 0 , 0 );
104+ }
105+
49106static char gurobi_con_sense (ConstraintSense sense)
50107{
51108 switch (sense)
0 commit comments