Skip to content

Commit ef357ee

Browse files
committed
first qt application launching a python script. with a segmentation fault, the second time the script is launched
1 parent 2306639 commit ef357ee

File tree

12 files changed

+206
-0
lines changed

12 files changed

+206
-0
lines changed

qt-5-pyqt5/CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
CMAKE_MINIMUM_REQUIRED(VERSION 3.4)
2+
3+
PROJECT(sample)
4+
5+
SET(CMAKE_CXX_STANDARD 14)
6+
7+
set(CMAKE_INCLUDE_CURRENT_DIR ON)
8+
9+
set(CMAKE_AUTOMOC ON)
10+
11+
find_package(Qt5Widgets)
12+
13+
set(PYBIND11_PYTHON_VERSION 3.4)
14+
15+
FIND_PACKAGE(pybind11 CONFIG)
16+
17+
ADD_DEFINITIONS(-DSCRIPTS_DIRECTORY="${CMAKE_SOURCE_DIR}")
18+
19+
ADD_EXECUTABLE(sample
20+
src/main.cpp
21+
src/sample.cpp
22+
src/mainwindow.cpp
23+
src/scripter.cpp
24+
)
25+
26+
target_link_libraries(sample
27+
Qt5::Widgets
28+
${PYTHON_LIBRARIES}
29+
pybind11::embed
30+
)
31+
32+
project(sampleapi)
33+
pybind11_add_module(sampleapi src/scripterAPI.cpp)

qt-5-pyqt5/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# c++ launches a Python script that loads a shared library module and sets a c++ variable
2+
3+
- Create a `.so` module.
4+
- Call the Python script from the c++ code and pass a variable per reference.
5+
- The Python script loads the module and modify the variable.
6+
- The c++ code checks that the values has been modified
7+
8+
~~~.sh
9+
$ mkdir build
10+
$ cmake -Dpybind11_DIR=/home/ale/bin/pybind11/share/cmake/pybind11 -DCMAKE_BUILD_TYPE=Debug ..
11+
$ make
12+
$ ./sample
13+
~~~
14+
15+
For now, you have to copy the generated `fooapi.cpython-35m-x86_64-linux-gnu.so` file next to the python script.

qt-5-pyqt5/python/set-bar.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import sampleapi
2+
3+
print(foo_copy.bar)
4+
foo_copy.bar = 5
5+
print(foo_copy.bar)
6+
foo_ref.bar = 5
7+

qt-5-pyqt5/src/main.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include <QDebug>
2+
3+
#include "sample.h"
4+
#include "mainwindow.h"
5+
6+
int main(int argc, char *argv[])
7+
{
8+
Sample app(argc, argv);
9+
10+
MainWindow mainWin;
11+
mainWin.show();
12+
13+
return app.exec();
14+
}

qt-5-pyqt5/src/mainwindow.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <iostream>
2+
#include "mainwindow.h"
3+
#include "scripter.h"
4+
5+
#include <QtWidgets>
6+
#include <QDebug>
7+
#include <QString>
8+
9+
MainWindow::MainWindow()
10+
{
11+
createActions();
12+
}
13+
14+
void MainWindow::createActions()
15+
{
16+
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
17+
QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
18+
exitAct->setShortcuts(QKeySequence::Quit);
19+
20+
QMenu *scriptMenu = menuBar()->addMenu(tr("&Script"));
21+
QAction *runAct = scriptMenu->addAction(tr("&Run"), this, &MainWindow::scriptRun);
22+
23+
QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
24+
QAction *aboutAct = helpMenu->addAction(tr("&About"), this, &MainWindow::about);
25+
// add an help entry that responds to F1
26+
}
27+
28+
void MainWindow::scriptRun()
29+
{
30+
QString fileName = QFileDialog::getOpenFileName(this,
31+
// tr("Open Image"), QStandardPaths::standardLocations(QStandardPaths::HomeLocation).last(), tr("Image Files (*.py *.png *.jpg *.bmp)"));
32+
tr("Open Image"), SCRIPTS_DIRECTORY, tr("Image Files (*.py *.png *.jpg *.bmp)"));
33+
qDebug() << "fileName" << fileName;
34+
std::cout << "filename: " << fileName.toStdString() << std::endl;
35+
36+
Scripter scripter;
37+
scripter.runFile(fileName.toStdString());
38+
}
39+
40+
void MainWindow::about()
41+
{
42+
QMessageBox::about(this, tr("About this sample"),
43+
tr("This <i>Sample</i> creates a window with a menu bar."));
44+
}

qt-5-pyqt5/src/mainwindow.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef MAINWINDOW_H
2+
#define MAINWINDOW_H
3+
4+
#include <QMainWindow>
5+
6+
class MainWindow : public QMainWindow
7+
{
8+
Q_OBJECT
9+
public:
10+
MainWindow();
11+
private slots:
12+
void scriptRun();
13+
void about();
14+
private:
15+
void createActions();
16+
};
17+
#endif

qt-5-pyqt5/src/sample.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#include "sample.h"
2+
3+
#include <QDebug>
4+
5+
Sample::Sample(int &argc, char *argv[]) :
6+
QApplication(argc, argv)
7+
{
8+
setApplicationName("Application Sample");
9+
setApplicationVersion("0.1");
10+
}

qt-5-pyqt5/src/sample.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef SAMPLE_H
2+
#define SAMPLE_H
3+
4+
#include<QApplication>
5+
6+
class Sample : public QApplication
7+
{
8+
Q_OBJECT
9+
public:
10+
explicit Sample(int &argc, char *argv[]);
11+
12+
};
13+
#endif

qt-5-pyqt5/src/scripter.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "scripter.h"
2+
#include "scripterAPI.h"
3+
4+
using namespace pybind11::literals;
5+
6+
void Scripter::runFile(std::string fileName)
7+
{
8+
ScripterAPI foo1, foo2;
9+
10+
auto module = py::module::import("sampleapi");
11+
12+
auto locals = py::dict("foo_copy"_a=foo1, "foo_ref"_a=py::cast(foo2, py::return_value_policy::reference)); // foo1 by value, foo2 by reference
13+
14+
py::eval_file(fileName, py::globals(), locals);
15+
16+
assert(foo1.bar == 1);
17+
assert(foo2.bar == 5);
18+
}

qt-5-pyqt5/src/scripter.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <string>
2+
#include <QString>
3+
4+
#undef slots // avoid conflicts between Python.h and Qt slots
5+
#include <pybind11/pybind11.h>
6+
#include <pybind11/embed.h>
7+
#define slots Q_SLOTS
8+
9+
namespace py = pybind11;
10+
11+
class Scripter
12+
{
13+
public:
14+
void runFile(std::string fileName);
15+
private:
16+
py::scoped_interpreter guard{}; // start the interpreter and keep it alive
17+
};

0 commit comments

Comments
 (0)