Skip to content

Commit

Permalink
Do not use macros if libscip is a shared library.
Browse files Browse the repository at this point in the history
The macros are not binary-compatible across different versions of
libscip, whereas the functions are. (That is because the macros poke
directly in structures whose layout changes from version to version,
because members are added and/or removed in the middle of the
structure.) So force JSCIP to always call the out-of-line functions
instead of the macros unless libscip is a static library (in which case
the macros are safe to use). (In that case, the static library has
hopefully been built with position-independent code enabled, but that is
a different matter, and we cannot easily check that here.) This should
make libjscip keep working if you swap the libscip under it, instead of
silently returning nonsense values for SCIPinfinity(). The performance
hit should be minimal, because this only affects calls from Java, which
go through 3 layers of Java wrappers (Scip, SCIPJNI, and SCIPJNIJNI) and
1 JNI call either way, so 1 C/C++ function call is not going to be a big
hit.

CMakeLists.txt: Check whether SCIP is a static library (in which case it
is safe to use macros), define -DHAVE_STATIC_LIBSCIP=1 in that case.

src/scipjni.i: #ifndef HAVE_STATIC_LIBSCIP, #undef any relevant macros
(with an #ifdef check because some compilers warn about #undef-ing
already undefined macros), also #define the BMS ones because the
functions are named differently (with a _call suffix) in that case. This
ensures that, if libscip is a shared library, we use function calls
instead of the macros.

src/scipjni_wrap.cxx: Regenerate.
  • Loading branch information
kkofler committed Jun 10, 2022
1 parent 84368ea commit 5db250f
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 0 deletions.
9 changes: 9 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,15 @@ else()
endif()
include_directories (${JNI_INCLUDE_DIRS} ${SCIP_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}/src)

#
# check whether SCIP is a static library (in which case it is safe to use macros)
#
get_target_property(LIBSCIP_TARGET_TYPE libscip TYPE)
message("libscip is a ${LIBSCIP_TARGET_TYPE}.")
if (LIBSCIP_TARGET_TYPE STREQUAL STATIC_LIBRARY)
add_definitions(-DHAVE_STATIC_LIBSCIP=1)
endif()

#
# link directories
#
Expand Down
62 changes: 62 additions & 0 deletions src/scipjni.i
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,68 @@
#include "scip/cons_quadratic.h"
#include "objscip/objmessagehdlr.h"

/* if libscip is a shared library, ensure we use function calls instead of
macros, for better binary compatibility across SCIP versions */
#ifndef HAVE_STATIC_LIBSCIP
#ifdef SCIPinfinity
#undef SCIPinfinity
#endif

#ifdef BMScheckEmptyMemory
#undef BMScheckEmptyMemory
#endif
#define BMScheckEmptyMemory() BMScheckEmptyMemory_call()

#ifdef BMSgetMemoryUsed
#undef BMSgetMemoryUsed
#endif
#define BMSgetMemoryUsed() BMSgetMemoryUsed_call()

#ifdef SCIPvarGetName
#undef SCIPvarGetName
#endif

#ifdef SCIPvarGetType
#undef SCIPvarGetType
#endif

#ifdef SCIPvarGetLbLocal
#undef SCIPvarGetLbLocal
#endif

#ifdef SCIPvarGetUbLocal
#undef SCIPvarGetUbLocal
#endif

#ifdef SCIPvarGetLbGlobal
#undef SCIPvarGetLbGlobal
#endif

#ifdef SCIPvarGetUbGlobal
#undef SCIPvarGetUbGlobal
#endif

#ifdef SCIPvarGetObj
#undef SCIPvarGetObj
#endif

#ifdef SCIPvarGetBranchPriority
#undef SCIPvarGetBranchPriority
#endif

#ifdef SCIPsolGetDepth
#undef SCIPsolGetDepth
#endif

#ifdef SCIPsolGetIndex
#undef SCIPsolGetIndex
#endif

#ifdef SCIPconsGetName
#undef SCIPconsGetName
#endif
#endif /* ndef HAVE_STATIC_LIBSCIP */

/* assist function to create a SCIP */
SCIP* createSCIP()
{
Expand Down
62 changes: 62 additions & 0 deletions src/scipjni_wrap.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,68 @@ namespace Swig {
#include "scip/cons_quadratic.h"
#include "objscip/objmessagehdlr.h"

/* if libscip is a shared library, ensure we use function calls instead of
macros, for better binary compatibility across SCIP versions */
#ifndef HAVE_STATIC_LIBSCIP
#ifdef SCIPinfinity
#undef SCIPinfinity
#endif

#ifdef BMScheckEmptyMemory
#undef BMScheckEmptyMemory
#endif
#define BMScheckEmptyMemory() BMScheckEmptyMemory_call()

#ifdef BMSgetMemoryUsed
#undef BMSgetMemoryUsed
#endif
#define BMSgetMemoryUsed() BMSgetMemoryUsed_call()

#ifdef SCIPvarGetName
#undef SCIPvarGetName
#endif

#ifdef SCIPvarGetType
#undef SCIPvarGetType
#endif

#ifdef SCIPvarGetLbLocal
#undef SCIPvarGetLbLocal
#endif

#ifdef SCIPvarGetUbLocal
#undef SCIPvarGetUbLocal
#endif

#ifdef SCIPvarGetLbGlobal
#undef SCIPvarGetLbGlobal
#endif

#ifdef SCIPvarGetUbGlobal
#undef SCIPvarGetUbGlobal
#endif

#ifdef SCIPvarGetObj
#undef SCIPvarGetObj
#endif

#ifdef SCIPvarGetBranchPriority
#undef SCIPvarGetBranchPriority
#endif

#ifdef SCIPsolGetDepth
#undef SCIPsolGetDepth
#endif

#ifdef SCIPsolGetIndex
#undef SCIPsolGetIndex
#endif

#ifdef SCIPconsGetName
#undef SCIPconsGetName
#endif
#endif /* ndef HAVE_STATIC_LIBSCIP */

/* assist function to create a SCIP */
SCIP* createSCIP()
{
Expand Down

0 comments on commit 5db250f

Please sign in to comment.