Skip to content
This repository was archived by the owner on Jun 25, 2020. It is now read-only.

Commit d82ae2b

Browse files
committed
feature: new implementation
1 parent 7e2b6a8 commit d82ae2b

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

src/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ endif()
2828
find_package(LibClang REQUIRED)
2929
find_package(Boost 1.54 COMPONENTS thread log regex system filesystem REQUIRED)
3030
find_package(ASPELL REQUIRED)
31+
find_package(PythonLibs 3 REQUIRED)
3132
set(LIBCLANGMM_INCLUDE_DIR ../libclangmm/src)
3233
set(TINY_PROCESS_INCLUDE_DIR ../tiny-process-library)
34+
set(PYBIND11_INCLUDE_DIR ../pybind11/include)
3335

3436
string(REPLACE libclang liblldb LIBLLDB_LIBRARIES "${LIBCLANG_LIBRARIES}")
3537
if(EXISTS "${LIBLLDB_LIBRARIES}")
@@ -48,6 +50,7 @@ endif()
4850
include(FindPkgConfig)
4951
pkg_check_modules(GTKMM gtkmm-3.0 REQUIRED)
5052
pkg_check_modules(GTKSVMM gtksourceviewmm-3.0 REQUIRED)
53+
pkg_check_modules(PYGOBJECT pygobject-3.0 REQUIRED)
5154

5255
set(global_includes
5356
${Boost_INCLUDE_DIRS}
@@ -57,6 +60,9 @@ set(global_includes
5760
${LIBCLANGMM_INCLUDE_DIR}
5861
${ASPELL_INCLUDE_DIR}
5962
${TINY_PROCESS_INCLUDE_DIR}
63+
${PYBIND11_INCLUDE_DIR}
64+
${PYTHON_INCLUDE_DIRS}
65+
${PYGOBJECT_INCLUDE_DIRS}
6066
)
6167

6268
set(global_libraries
@@ -66,6 +72,8 @@ set(global_libraries
6672
${Boost_LIBRARIES}
6773
${ASPELL_LIBRARIES}
6874
${LIBLLDB_LIBRARIES}
75+
${PYTHON_LIBRARIES}
76+
${PYGOBJECT_LIBRARIES}
6977
)
7078

7179
set(project_files
@@ -95,6 +103,8 @@ set(project_files
95103
project.h
96104
project_build.h
97105
project_build.cc
106+
python_interpreter.cc
107+
python_interpreter.h
98108
selectiondialog.cc
99109
selectiondialog.h
100110
source.cc

src/python_interpreter.cc

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
#include "python_interpreter.h"
2+
#include "notebook.h"
3+
#include "config.h"
4+
#include <iostream>
5+
#include <pygobject.h>
6+
7+
inline pybind11::module pyobject_from_gobj(gpointer ptr){
8+
auto obj=G_OBJECT(ptr);
9+
if(obj)
10+
return pybind11::module(pygobject_new(obj), false);
11+
return pybind11::module(Py_None, false);
12+
}
13+
14+
PythonInterpreter::PythonInterpreter(){
15+
auto init_juci_api=[](){
16+
pybind11::module(pygobject_init(-1,-1,-1), false);
17+
pybind11::module api("jucpp", "Python bindings for juCi++");
18+
api.def("get_current_text_buffer", [](){
19+
auto view=Notebook::get().get_current_view();
20+
if(view)
21+
return pyobject_from_gobj(view->gobj());
22+
return pybind11::module(Py_None, false);
23+
});
24+
return api.ptr();
25+
};
26+
PyImport_AppendInittab("jucipp", init_juci_api);
27+
Py_Initialize();
28+
// long unsigned size = 0L;
29+
// argv=Py_DecodeLocale("",&size);
30+
// PySys_SetArgv(0,&argv);
31+
Config::get().load();
32+
add_path("/usr/lib/python3.5/site-packages");// Config::get().python.site_packages);
33+
auto plugin_path=Config::get().juci_home_path()/"plugins"; // Config::get().python.plugin_directory;
34+
add_path(plugin_path);
35+
boost::filesystem::directory_iterator end_it;
36+
for(boost::filesystem::directory_iterator it(plugin_path);it!=end_it;it++){
37+
auto module_name=it->path().stem().string();
38+
if(module_name!="__pycache__"){
39+
auto module=import(module_name);
40+
if(!module){
41+
auto err=PythonError();
42+
if(err)
43+
std::cerr << std::string(err) << std::endl;
44+
}
45+
}
46+
}
47+
}
48+
49+
pybind11::module PythonInterpreter::get_loaded_module(const std::string &module_name){
50+
return pybind11::module(PyImport_AddModule(module_name.c_str()), true);
51+
}
52+
53+
pybind11::module PythonInterpreter::import(const std::string &module_name){
54+
return pybind11::module(PyImport_ImportModule(module_name.c_str()), false);
55+
}
56+
57+
void PythonInterpreter::add_path(const boost::filesystem::path &path){
58+
std::wstring sys_path(Py_GetPath());
59+
if(!sys_path.empty())
60+
#ifdef _WIN32
61+
sys_path += ';';
62+
#else
63+
sys_path += ':';
64+
#endif
65+
sys_path += path.generic_wstring();
66+
Py_SetPath(sys_path.c_str());
67+
}
68+
69+
PythonInterpreter::~PythonInterpreter(){
70+
auto err=PythonError();
71+
if(Py_IsInitialized())
72+
Py_Finalize();
73+
if(err)
74+
std::cerr << std::string(err) << std::endl;
75+
}
76+
77+
PythonError::PythonError(){
78+
pybind11::object error(PyErr_Occurred(), false);
79+
if(error){
80+
PyObject *exception,*value,*traceback;
81+
PyErr_Fetch(&exception,&value,&traceback);
82+
PyErr_NormalizeException(&exception,&value,&traceback);
83+
try{
84+
exp=std::string(pybind11::object(exception,false).str());
85+
val=std::string(pybind11::object(value,false).str());
86+
trace=std::string(pybind11::object(traceback,false).str());
87+
} catch (const std::runtime_error &e){
88+
exp=e.what();
89+
}
90+
}
91+
}
92+
93+
PythonError::operator std::string(){
94+
return exp + "\n" + val + "\n" + trace;
95+
}
96+
97+
PythonError::operator bool(){
98+
return !exp.empty();
99+
}

src/python_interpreter.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#ifndef JUCI_PYTHON_INTERPRETER_H_
2+
#define JUCI_PYTHON_INTERPRETER_H_
3+
4+
#include <pybind11/pybind11.h>
5+
#include <boost/filesystem/path.hpp>
6+
7+
#include <iostream>
8+
using namespace std;
9+
10+
class PythonInterpreter {
11+
private:
12+
PythonInterpreter();
13+
~PythonInterpreter();
14+
wchar_t *argv;
15+
public:
16+
static PythonInterpreter& get(){
17+
static PythonInterpreter singleton;
18+
return singleton;
19+
}
20+
pybind11::module get_loaded_module(const std::string &module_name);
21+
pybind11::module import(const std::string &module_name);
22+
void add_path(const boost::filesystem::path &path);
23+
};
24+
25+
class PythonError {
26+
public:
27+
PythonError();
28+
operator std::string();
29+
operator bool();
30+
std::string exp, val, trace;
31+
};
32+
33+
#endif // JUCI_PYTHON_INTERPRETER_H_

0 commit comments

Comments
 (0)