Adding SWIG Java wrappers to LightGBM (#1223)

* Adding Java wrappers to LightGBM by updating CMakeLists and adding SWIG file

* Set SWIG generation to OFF by default

* Added -package option to SWIG_FLAGS

* Fixed jar structure to have class files in proper location

* removed link with OpenMP flags
This commit is contained in:
Ilya Matiach 2018-01-31 01:20:41 -05:00 коммит произвёл Guolin Ke
Родитель d22de3c2ff
Коммит 6d58decf51
2 изменённых файлов: 132 добавлений и 1 удалений

Просмотреть файл

@ -11,6 +11,7 @@ PROJECT(lightgbm)
OPTION(USE_MPI "MPI based parallel learning" OFF)
OPTION(USE_OPENMP "Enable OpenMP" ON)
OPTION(USE_GPU "Enable GPU-acclerated training (EXPERIMENTAL)" OFF)
OPTION(USE_SWIG "Enable SWIG to generate Java API" OFF)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.8.2")
@ -28,6 +29,25 @@ if(APPLE)
OPTION(APPLE_OUTPUT_DYLIB "Output dylib shared library" OFF)
endif()
if(USE_SWIG)
find_package(SWIG REQUIRED)
find_package(Java REQUIRED)
find_package(JNI REQUIRED)
include(UseJava)
include(UseSWIG)
set(SWIG_CXX_EXTENSION "cxx")
set(SWIG_EXTRA_LIBRARIES "")
set(SWIG_JAVA_EXTRA_FILE_EXTENSIONS ".java" "JNI.java")
set(SWIG_MODULE_JAVA_LANGUAGE "JAVA")
set(SWIG_MODULE_JAVA_SWIG_LANGUAGE_FLAG "java")
set(CMAKE_SWIG_OUTDIR "${CMAKE_CURRENT_BINARY_DIR}/java")
FILE(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/com/microsoft/ml/lightgbm/linux/x86_64")
include_directories(Java_INCLUDE_DIRS)
include_directories(JNI_INCLUDE_DIRS)
include_directories($ENV{JAVA_HOME}/include)
include_directories($ENV{JAVA_HOME}/include/linux)
endif(USE_SWIG)
if(USE_MPI)
find_package(MPI REQUIRED)
ADD_DEFINITIONS(-DUSE_MPI)
@ -127,6 +147,18 @@ file(GLOB SOURCES
add_executable(lightgbm src/main.cpp ${SOURCES})
add_library(_lightgbm SHARED src/c_api.cpp src/lightgbm_R.cpp ${SOURCES})
if(USE_SWIG)
set_property(SOURCE swig/lightgbmlib.i PROPERTY CPLUSPLUS ON)
LIST(APPEND swig_options -package com.microsoft.ml.lightgbm)
set_property(SOURCE swig/lightgbmlib.i PROPERTY SWIG_FLAGS "${swig_options}")
swig_add_module(_lightgbm_swig java swig/lightgbmlib.i)
swig_link_libraries(_lightgbm_swig _lightgbm)
add_custom_command(TARGET _lightgbm_swig POST_BUILD
COMMAND "${Java_JAVAC_EXECUTABLE}" -d . java/*.java
COMMAND cp "${PROJECT_SOURCE_DIR}/*.so" com/microsoft/ml/lightgbm/linux/x86_64
COMMAND "${Java_JAR_EXECUTABLE}" -cf lightgbmlib.jar com)
endif(USE_SWIG)
if(MSVC)
set_target_properties(_lightgbm PROPERTIES OUTPUT_NAME "lib_lightgbm")
endif(MSVC)

99
swig/lightgbmlib.i Normal file
Просмотреть файл

@ -0,0 +1,99 @@
/* lightgbmlib.i */
%module lightgbmlib
%ignore LGBM_BoosterSaveModelToString;
%{
/* Includes the header in the wrapper code */
#include "../include/LightGBM/export.h"
#include "../include/LightGBM/utils/log.h"
#include "../include/LightGBM/c_api.h"
%}
/* header files */
%include "../include/LightGBM/export.h"
%include "../include/LightGBM/c_api.h"
%include "cpointer.i"
%include "carrays.i"
%inline %{
char * LGBM_BoosterSaveModelToStringSWIG(BoosterHandle handle,
int num_iteration,
int64_t buffer_len,
int64_t* out_len) {
char* dst = new char[buffer_len];
int result = LGBM_BoosterSaveModelToString(handle, num_iteration, buffer_len, out_len, dst);
if (result != 0) {
return nullptr;
}
return dst;
}
%}
%pointer_functions(int, intp)
%pointer_functions(long, longp)
%pointer_functions(double, doublep)
%pointer_functions(float, floatp)
%pointer_functions(int64_t, int64_tp)
%pointer_functions(int32_t, int32_tp)
%pointer_cast(int64_t *, long *, int64_t_to_long_ptr)
%pointer_cast(int64_t *, double *, int64_t_to_double_ptr)
%pointer_cast(int32_t *, int *, int32_t_to_int_ptr)
%pointer_cast(long *, int64_t *, long_to_int64_t_ptr)
%pointer_cast(double *, int64_t *, double_to_int64_t_ptr)
%pointer_cast(double *, void *, double_to_voidp_ptr)
%pointer_cast(int *, int32_t *, int_to_int32_t_ptr)
%pointer_cast(float *, void *, float_to_voidp_ptr)
%array_functions(double, doubleArray)
%array_functions(float, floatArray)
%array_functions(int, intArray)
%array_functions(long, longArray)
/* Custom pointer manipulation template */
%define %pointer_manipulation(TYPE,NAME)
%{
static TYPE *new_##NAME() { %}
%{ TYPE* NAME = new TYPE; return NAME; %}
%{}
static void delete_##NAME(TYPE *self) { %}
%{ if (self) delete self; %}
%{}
%}
TYPE *new_##NAME();
void delete_##NAME(TYPE *self);
%enddef
%define %pointer_dereference(TYPE,NAME)
%{
static TYPE NAME ##_value(TYPE *self) {
TYPE NAME = *self;
return NAME;
}
%}
TYPE NAME##_value(TYPE *self);
%enddef
%define %pointer_handle(TYPE,NAME)
%{
static TYPE* NAME ##_handle() { %}
%{ TYPE* NAME = new TYPE; *NAME = (TYPE)operator new(sizeof(int*)); return NAME; %}
%{}
%}
TYPE *NAME##_handle();
%enddef
%pointer_manipulation(void*, voidpp)
/* Allow dereferencing of void** to void* */
%pointer_dereference(void*, voidpp)
/* Allow retrieving handle to void** */
%pointer_handle(void*, voidpp)