diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 79f83bb4..2acbea37 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -4,7 +4,11 @@ cmake_minimum_required(VERSION 3.1)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
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)
@@ -68,15 +72,34 @@ find_package(Radare2 REQUIRED)
include_directories(${RADARE2_INCLUDE_DIRS})
link_directories(${RADARE2_LIBRARY_DIRS})
-if(CUTTER_ENABLE_JUPYTER)
- find_package(PythonLibs 3.3)
+if(CUTTER_ENABLE_PYTHON)
+ find_package(PythonLibs ${CUTTER_PYTHON_MIN})
if(NOT PythonLibs_FOUND)
- message(FATAL_ERROR "Python >= 3.3 could not be found which is required for Jupyter integration.
-If you do not want to enable Jupyter, re-run CMake with -DCUTTER_ENABLE_JUPYTER=OFF.")
+ message(FATAL_ERROR "Python >= ${CUTTER_PYTHON_MIN} could not be found.
+If you do not want to build Cutter with Python, re-run CMake with -DCUTTER_ENABLE_PYTHON=OFF.")
endif()
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()
@@ -86,7 +109,14 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
endif()
+message(STATUS "")
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)
@@ -94,15 +124,42 @@ qmake_configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CutterConfig.h.in"
"${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 ${RADARE2_LIBRARIES})
-if(CUTTER_ENABLE_JUPYTER)
+if(CUTTER_ENABLE_PYTHON)
target_link_libraries(Cutter ${PYTHON_LIBRARIES})
- if(CUTTER_ENABLE_QTWEBENGINE)
- target_link_libraries(Cutter Qt5::WebEngineWidgets)
+ if(CUTTER_ENABLE_PYTHON_BINDINGS)
+ target_link_libraries(Cutter ${SHIBOKEN_LIBRARY} ${PYSIDE_LIBRARY})
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)
diff --git a/src/bindings/bindings.h b/src/bindings/bindings.h
new file mode 100644
index 00000000..d3a81668
--- /dev/null
+++ b/src/bindings/bindings.h
@@ -0,0 +1,8 @@
+
+#ifndef CUTTER_BINDINGS_H
+#define CUTTER_BINDINGS_H
+
+//#include "../widgets/CutterDockWidget.h"
+#include "../Cutter.h"
+
+#endif //CUTTER_BINDINGS_H
diff --git a/src/bindings/bindings.txt.in b/src/bindings/bindings.txt.in
new file mode 100644
index 00000000..465e2876
--- /dev/null
+++ b/src/bindings/bindings.txt.in
@@ -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
\ No newline at end of file
diff --git a/src/bindings/bindings.xml b/src/bindings/bindings.xml
new file mode 100644
index 00000000..81868fd5
--- /dev/null
+++ b/src/bindings/bindings.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/common/PythonAPI.h b/src/common/PythonAPI.h
index 664c86ac..f73da892 100644
--- a/src/common/PythonAPI.h
+++ b/src/common/PythonAPI.h
@@ -1,7 +1,7 @@
#ifndef PYTHONAPI_H
#define PYTHONAPI_H
-#ifdef CUTTER_ENABLE_JUPYTER
+#ifdef CUTTER_ENABLE_PYTHON
#include
diff --git a/src/common/PythonManager.cpp b/src/common/PythonManager.cpp
index 6443bc7c..e8bf77b9 100644
--- a/src/common/PythonManager.cpp
+++ b/src/common/PythonManager.cpp
@@ -53,13 +53,18 @@ void PythonManager::initPythonHome()
}
}
+extern "C" PyObject *PyInit_CutterBindings();
+
void PythonManager::initialize()
{
initPythonHome();
PyImport_AppendInittab("_cutter", &PyInit_api);
+#ifdef CUTTER_ENABLE_JUPYTER
PyImport_AppendInittab("cutter_internal", &PyInit_api_internal);
+#endif
PyImport_AppendInittab("_qtres", &PyInit_qtres);
+ PyImport_AppendInittab("CutterBindings", &PyInit_CutterBindings);
Py_Initialize();
PyEval_InitThreads();
diff --git a/src/common/QtResImporter.cpp b/src/common/QtResImporter.cpp
index c6178e53..b38a7195 100644
--- a/src/common/QtResImporter.cpp
+++ b/src/common/QtResImporter.cpp
@@ -1,4 +1,4 @@
-#ifdef CUTTER_ENABLE_JUPYTER
+#ifdef CUTTER_ENABLE_PYTHON
#include
#include
@@ -100,4 +100,4 @@ PyObject *PyInit_qtres()
return PyModule_Create(&QtResModule);
}
-#endif // CUTTER_ENABLE_JUPYTER
+#endif // CUTTER_ENABLE_PYTHON
diff --git a/src/common/QtResImporter.h b/src/common/QtResImporter.h
index 54203a6d..a3cf470c 100644
--- a/src/common/QtResImporter.h
+++ b/src/common/QtResImporter.h
@@ -1,7 +1,7 @@
#ifndef QTRESIMPORTER_H
#define QTRESIMPORTER_H
-#ifdef CUTTER_ENABLE_JUPYTER
+#ifdef CUTTER_ENABLE_PYTHON
PyObject *PyInit_qtres();
@@ -9,6 +9,6 @@ PyObject *QtResImport(const char *name);
#define RegQtResImporter() Py_DecRef(QtResImport("reg_qtres_importer"))
-#endif // CUTTER_ENABLE_JUPYTER
+#endif // CUTTER_ENABLE_PYTHON
#endif // QTRESIMPORTER_H
diff --git a/src/plugins/plugin_sample.py b/src/plugins/plugin_sample.py
index ddf883dd..a9abfbfb 100644
--- a/src/plugins/plugin_sample.py
+++ b/src/plugins/plugin_sample.py
@@ -3,7 +3,7 @@ from cutter_plugin import CutterPlugin
from PySide2 import QtWidgets
from PySide2.QtCore import QObject, SIGNAL, Qt
from PySide2.QtGui import QFont
-
+import CutterBindings
class CutterSamplePlugin(CutterPlugin):
name = "SamplePlugin"
@@ -36,14 +36,13 @@ class CutterSamplePlugin(CutterPlugin):
layout.addWidget(button)
layout.setAlignment(button, Qt.AlignHCenter)
- # TODO How to access CutterCore::seekChanged?
- # QObject.connect(cutter.core() ?, cutter.???)
- QObject.connect(button, SIGNAL("clicked()"), self.on_button_clicked)
+ QObject.connect(CutterBindings.CutterCore.getInstance(), SIGNAL("seekChanged(RVA)"), self.generate_fortune)
+ QObject.connect(button, SIGNAL("clicked()"), self.generate_fortune)
return self.makeCppPointer(dock_widget)
- def on_button_clicked(self):
+ def generate_fortune(self):
res = cutter.cmd("?E `fo`")
self.text.setText(res)