Generate Bindings for CutterCore in CMake

Refactor CMakeLists.txt for bindings

Fix for CUTTER_ENABLE_JUPYTER=OFF
This commit is contained in:
Florian Märkl 2019-02-03 16:03:36 +01:00
parent 1c98a1c42e
commit 23115d7b1c
9 changed files with 114 additions and 20 deletions

View File

@ -4,7 +4,11 @@ cmake_minimum_required(VERSION 3.1)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(DisallowInSource) include(DisallowInSource)
option(CUTTER_ENABLE_JUPYTER "Enable Jupyter integration. Requires Python >= 3.3." ON) set(CUTTER_PYTHON_MIN 3.3)
option(CUTTER_ENABLE_PYTHON "Enable Python integration. Requires Python >= ${CUTTER_PYTHON_MIN}." ON)
option(CUTTER_ENABLE_PYTHON_BINDINGS "Enable generating Python bindings with Shiboken2. Unused if CUTTER_ENABLE_PYTHON=OFF." ON)
option(CUTTER_ENABLE_JUPYTER "Enable Jupyter integration. Unused if CUTTER_ENABLE_PYTHON=OFF." ON)
option(CUTTER_ENABLE_QTWEBENGINE "Use QtWebEngine for in-app Jupyter Browser. Unused if CUTTER_ENABLE_JUPYTER=OFF." OFF) option(CUTTER_ENABLE_QTWEBENGINE "Use QtWebEngine for in-app Jupyter Browser. Unused if CUTTER_ENABLE_JUPYTER=OFF." OFF)
@ -68,15 +72,34 @@ find_package(Radare2 REQUIRED)
include_directories(${RADARE2_INCLUDE_DIRS}) include_directories(${RADARE2_INCLUDE_DIRS})
link_directories(${RADARE2_LIBRARY_DIRS}) link_directories(${RADARE2_LIBRARY_DIRS})
if(CUTTER_ENABLE_JUPYTER) if(CUTTER_ENABLE_PYTHON)
find_package(PythonLibs 3.3) find_package(PythonLibs ${CUTTER_PYTHON_MIN})
if(NOT PythonLibs_FOUND) if(NOT PythonLibs_FOUND)
message(FATAL_ERROR "Python >= 3.3 could not be found which is required for Jupyter integration. message(FATAL_ERROR "Python >= ${CUTTER_PYTHON_MIN} could not be found.
If you do not want to enable Jupyter, re-run CMake with -DCUTTER_ENABLE_JUPYTER=OFF.") If you do not want to build Cutter with Python, re-run CMake with -DCUTTER_ENABLE_PYTHON=OFF.")
endif() endif()
include_directories(${PYTHON_INCLUDE_DIRS}) include_directories(${PYTHON_INCLUDE_DIRS})
add_definitions(-DCUTTER_ENABLE_JUPYTER) add_definitions(-DCUTTER_ENABLE_PYTHON)
if(CUTTER_ENABLE_JUPYTER)
add_definitions(-DCUTTER_ENABLE_JUPYTER)
endif()
if(CUTTER_ENABLE_PYTHON_BINDINGS)
find_package(Shiboken2)
find_package(PySide2)
if((NOT Shiboken2_FOUND) OR (NOT PySide2_FOUND))
message(FATAL_ERROR "Generating Python bindings is enabled, but Shiboken2 or PySide2 was not found.
If you explicitly want to not generate bindings, re-run CMake with -DCUTTER_ENABLE_PYTHON_BINDINGS=OFF
or, if you don't want to build with Python at all, use -DCUTTER_ENABLE_PYTHON=OFF.")
endif()
include_directories(${SHIBOKEN_INCLUDE_DIR})
include_directories(${PYSIDE_INCLUDE_DIR})
include_directories(${PYSIDE_INCLUDE_DIR}/QtCore)
endif()
endif() endif()
@ -86,7 +109,14 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
endif() endif()
message(STATUS "")
message(STATUS "Building Cutter version ${CUTTER_VERSION_FULL}") message(STATUS "Building Cutter version ${CUTTER_VERSION_FULL}")
message(STATUS "Options:")
message(STATUS "- Python: ${CUTTER_ENABLE_PYTHON}")
message(STATUS "- Python Bindings: ${CUTTER_ENABLE_PYTHON_BINDINGS}")
message(STATUS "- Jupyter: ${CUTTER_ENABLE_JUPYTER}")
message(STATUS "- QtWebEngine: ${CUTTER_ENABLE_QTWEBENGINE}")
message(STATUS "")
include(QMakeConfigureFile) include(QMakeConfigureFile)
@ -94,15 +124,42 @@ qmake_configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CutterConfig.h.in"
"${CMAKE_CURRENT_BINARY_DIR}/CutterConfig.h") "${CMAKE_CURRENT_BINARY_DIR}/CutterConfig.h")
set(BINDINGS_SOURCE
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/cutterbindings_module_wrapper.cpp"
#"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/cutterdockwidget_wrapper.cpp"
"${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings/cuttercore_wrapper.cpp")
add_executable(Cutter ${UI_FILES} ${QRC_FILES} ${SOURCE_FILES} ${HEADER_FILES}) set_property(SOURCE ${BINDINGS_SOURCE} PROPERTY SKIP_AUTOGEN ON)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/bindings/CutterBindings")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/widgets")
add_custom_command(OUTPUT ${BINDINGS_SOURCE}
COMMAND shiboken2 --project-file=${CMAKE_CURRENT_BINARY_DIR}/bindings/bindings.txt
#DEPENDS ${sample_TYPESYSTEM} ${CMAKE_CURRENT_SOURCE_DIR}/global.h shiboken2
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Generating Python bindings with shiboken2")
add_executable(Cutter ${UI_FILES} ${QRC_FILES} ${SOURCE_FILES} ${HEADER_FILES} ${BINDINGS_SOURCE})
target_link_libraries(Cutter Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Svg Qt5::Network) target_link_libraries(Cutter Qt5::Core Qt5::Widgets Qt5::Gui Qt5::Svg Qt5::Network)
target_link_libraries(Cutter ${RADARE2_LIBRARIES}) target_link_libraries(Cutter ${RADARE2_LIBRARIES})
if(CUTTER_ENABLE_JUPYTER) if(CUTTER_ENABLE_PYTHON)
target_link_libraries(Cutter ${PYTHON_LIBRARIES}) target_link_libraries(Cutter ${PYTHON_LIBRARIES})
if(CUTTER_ENABLE_QTWEBENGINE) if(CUTTER_ENABLE_PYTHON_BINDINGS)
target_link_libraries(Cutter Qt5::WebEngineWidgets) target_link_libraries(Cutter ${SHIBOKEN_LIBRARY} ${PYSIDE_LIBRARY})
endif() endif()
endif() endif()
if(CUTTER_ENABLE_PYTHON AND CUTTER_ENABLE_JUPYTER AND CUTTER_ENABLE_QTWEBENGINE)
target_link_libraries(Cutter Qt5::WebEngineWidgets)
endif()
get_target_property(BINDINGS_INCLUDE_DIRS Cutter INCLUDE_DIRECTORIES)
list(APPEND BINDINGS_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}")
string(REPLACE ";" ":" BINDINGS_INCLUDE_DIRS "${BINDINGS_INCLUDE_DIRS}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bindings/bindings.txt.in"
"${CMAKE_CURRENT_BINARY_DIR}/bindings/bindings.txt" @ONLY)

8
src/bindings/bindings.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef CUTTER_BINDINGS_H
#define CUTTER_BINDINGS_H
//#include "../widgets/CutterDockWidget.h"
#include "../Cutter.h"
#endif //CUTTER_BINDINGS_H

View File

@ -0,0 +1,17 @@
[generator-project]
generator-set = shiboken
header-file = @CMAKE_CURRENT_SOURCE_DIR@/bindings/bindings.h
typesystem-file = @CMAKE_CURRENT_SOURCE_DIR@/bindings/bindings.xml
output-directory = @CMAKE_CURRENT_BINARY_DIR@/bindings
include-path = @BINDINGS_INCLUDE_DIRS@
typesystem-paths=@PYSIDE_TYPESYSTEMS@
enable-parent-ctor-heuristic
enable-pyside-extensions
enable-return-value-heuristic
use-isnull-as-nb_nonzero

View File

@ -0,0 +1,8 @@
<?xml version="1.0"?>
<typesystem package="CutterBindings">
<load-typesystem name="typesystem_core.xml" generate="no" />
<primitive-type name="bool"/>
<primitive-type name="std::string"/>
<!--<object-type name="CutterDockWidget" />-->
<object-type name="CutterCore" />
</typesystem>

View File

@ -1,7 +1,7 @@
#ifndef PYTHONAPI_H #ifndef PYTHONAPI_H
#define PYTHONAPI_H #define PYTHONAPI_H
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_PYTHON
#include <Python.h> #include <Python.h>

View File

@ -53,13 +53,18 @@ void PythonManager::initPythonHome()
} }
} }
extern "C" PyObject *PyInit_CutterBindings();
void PythonManager::initialize() void PythonManager::initialize()
{ {
initPythonHome(); initPythonHome();
PyImport_AppendInittab("_cutter", &PyInit_api); PyImport_AppendInittab("_cutter", &PyInit_api);
#ifdef CUTTER_ENABLE_JUPYTER
PyImport_AppendInittab("cutter_internal", &PyInit_api_internal); PyImport_AppendInittab("cutter_internal", &PyInit_api_internal);
#endif
PyImport_AppendInittab("_qtres", &PyInit_qtres); PyImport_AppendInittab("_qtres", &PyInit_qtres);
PyImport_AppendInittab("CutterBindings", &PyInit_CutterBindings);
Py_Initialize(); Py_Initialize();
PyEval_InitThreads(); PyEval_InitThreads();

View File

@ -1,4 +1,4 @@
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_PYTHON
#include <Python.h> #include <Python.h>
#include <marshal.h> #include <marshal.h>
@ -100,4 +100,4 @@ PyObject *PyInit_qtres()
return PyModule_Create(&QtResModule); return PyModule_Create(&QtResModule);
} }
#endif // CUTTER_ENABLE_JUPYTER #endif // CUTTER_ENABLE_PYTHON

View File

@ -1,7 +1,7 @@
#ifndef QTRESIMPORTER_H #ifndef QTRESIMPORTER_H
#define QTRESIMPORTER_H #define QTRESIMPORTER_H
#ifdef CUTTER_ENABLE_JUPYTER #ifdef CUTTER_ENABLE_PYTHON
PyObject *PyInit_qtres(); PyObject *PyInit_qtres();
@ -9,6 +9,6 @@ PyObject *QtResImport(const char *name);
#define RegQtResImporter() Py_DecRef(QtResImport("reg_qtres_importer")) #define RegQtResImporter() Py_DecRef(QtResImport("reg_qtres_importer"))
#endif // CUTTER_ENABLE_JUPYTER #endif // CUTTER_ENABLE_PYTHON
#endif // QTRESIMPORTER_H #endif // QTRESIMPORTER_H

View File

@ -3,7 +3,7 @@ from cutter_plugin import CutterPlugin
from PySide2 import QtWidgets from PySide2 import QtWidgets
from PySide2.QtCore import QObject, SIGNAL, Qt from PySide2.QtCore import QObject, SIGNAL, Qt
from PySide2.QtGui import QFont from PySide2.QtGui import QFont
import CutterBindings
class CutterSamplePlugin(CutterPlugin): class CutterSamplePlugin(CutterPlugin):
name = "SamplePlugin" name = "SamplePlugin"
@ -36,14 +36,13 @@ class CutterSamplePlugin(CutterPlugin):
layout.addWidget(button) layout.addWidget(button)
layout.setAlignment(button, Qt.AlignHCenter) layout.setAlignment(button, Qt.AlignHCenter)
# TODO How to access CutterCore::seekChanged? QObject.connect(CutterBindings.CutterCore.getInstance(), SIGNAL("seekChanged(RVA)"), self.generate_fortune)
# QObject.connect(cutter.core() ?, cutter.???) QObject.connect(button, SIGNAL("clicked()"), self.generate_fortune)
QObject.connect(button, SIGNAL("clicked()"), self.on_button_clicked)
return self.makeCppPointer(dock_widget) return self.makeCppPointer(dock_widget)
def on_button_clicked(self): def generate_fortune(self):
res = cutter.cmd("?E `fo`") res = cutter.cmd("?E `fo`")
self.text.setText(res) self.text.setText(res)