How to send signal using callback called from external script? - python

Introduction
I'm trying to update QT GUI element basing on the state of calculations in embedded python script. I'm able to extract required values from python, but can't set a reference to c++ object to make it work.
The details
Let's assume python code is called (in calc.cpp) this way:
void class_name::transfer(varA, varB, varC)
{
Py_Initialize();
emit inprogress(70); //HERE IT WORKS
object module = import("__main__");
object name_space = module.attr("__dict__");
exec_file("MyModule.py", name_space, name_space);
object MyFunc = name_space["MyFunc"];
object result = MyFunc(varA, varB, varC, callback);
double ret = extract<double>(result);
Py_Finalize();
}
void class_name::callback(double t_prog, double t_final)
{
progr = (double)t_prog / t_final * 100;
cout << progr; //To check if value is updating (It is)
emit inprogress(progr); //HERE IT FAIL
}
callback is a static member function (in calc.cpp) I use to extract some values, indicating on which stage is calculation inside python script. It is called in loop from python script (MyModule.py):
while r.successful() and k < num_steps:
r.integrate(r.t + delta_t)
callback(r.t, t_final)
However the compilation fails with following error:
illegal call to nonstatic member function
nonstatic member reference must be relative to specific object
It is related to emit inprogress(progr);
The Question
I think I should pass a reference to the object from my c++ to python, and back to c++ with callback. But I can't find a way how to do this. What's the correct way to do this?
Tested ideas (still not working)
I was trying to pass it simple like:
void class_name::callback(double t_prog, double t_final, class_name &cssd) but python seems to can't convert it automatically.
Creating of new class object:
class_name cs;
emit cs.inprogress(progr);
Compile without error, but signal never reach the slot - it creates new object instead of refer to existing.

We need to add some additional state to the callback, namely a reference to the instance of the class whose member function we want to invoke.
To do this, we can use a class. To make the functionality equivalent to just using a simple static callback function, let's define operator() (i.e. make it a functor), and also expose this operator to Python.
Let's suppose we have the following application class:
class app
{
public:
explicit app(std::string name) : name_(std::move(name)) {}
int run();
void callback(double t_prog, double t_final);
private:
std::string name_;
};
In run() we execute our Python script, and we want it to call the member function callback of the current instance.
Let's define the following callback handler class:
class callback_handler
{
public:
explicit callback_handler(app& a) : app_(a) {}
void operator()(double t_prog, double t_final)
{
app_.callback(t_prog, t_final);
}
private:
app& app_;
};
We need to expose this class to Python, but don't want to be able to create new instances from Python, nor do we really want it to be copied (although it doesn't really matter here, since our state only consists of references).
BOOST_PYTHON_MODULE(cbtest)
{
bp::class_<callback_handler, boost::noncopyable>("callback_handler", bp::no_init)
.def("__call__", &callback_handler::operator())
;
};
At the start of our application, we need to make sure to initialize our module before we use it -- call initcbtest(); right after initializing the Python interpreter.
Now we can use our callback handler in the following manner (The Python code stays the same, since the object is callable):
callback_handler cbh(*this);
bp::object result = MyFunc(1, 10, 2, boost::ref(cbh));
std::cout << "result = " << bp::extract<double>(result) << "\n";
Sample Code
#include <boost/noncopyable.hpp>
#include <boost/python.hpp>
#include <iostream>
// ============================================================================
namespace bp = boost::python;
// ============================================================================
class app
{
public:
explicit app(std::string name) : name_(std::move(name)) {}
int run();
void callback(double t_prog, double t_final);
private:
std::string name_;
};
// ============================================================================
class callback_handler
{
public:
explicit callback_handler(app& a) : app_(a) {}
void operator()(double t_prog, double t_final)
{
app_.callback(t_prog, t_final);
}
private:
app& app_;
};
// ----------------------------------------------------------------------------
BOOST_PYTHON_MODULE(cbtest)
{
bp::class_<callback_handler, boost::noncopyable>("callback_handler", bp::no_init)
.def("__call__", &callback_handler::operator())
;
};
// ============================================================================
void app::callback(double t_prog, double t_final)
{
std::cout << "CB(" << name_ << ") " << t_prog << " " << t_final << "\n";
}
// ----------------------------------------------------------------------------
int app::run()
{
Py_Initialize();
initcbtest();
try {
bp::object module = bp::import("__main__");
bp::object name_space = module.attr("__dict__");
bp::exec_file("MyModule.py", name_space, name_space);
bp::object MyFunc = name_space["MyFunc"];
callback_handler cbh(*this);
bp::object result = MyFunc(1, 10, 2, boost::ref(cbh));
std::cout << "result = " << bp::extract<double>(result) << "\n";
} catch (bp::error_already_set&) {
PyErr_Print();
}
Py_Finalize();
return 0;
}
// ============================================================================
int main()
{
app a("TestApp");
return a.run();
}
// ============================================================================
Python Script
File MyModule.py:
def MyFunc(a, b, c, callback):
result = 0
for i in range(a, b, c):
result += i
callback(i, b)
return result
Console Output
CB(TestApp) 0 10
CB(TestApp) 2 10
CB(TestApp) 4 10
CB(TestApp) 6 10
CB(TestApp) 8 10
result = 20

Maybe the problem is that you are calling emit c_n.inprogress(progr);, where the argument of the signal progr is of type double, whereas in the connect(sender, SIGNAL( inprogress(int) ), ui->progressBar, SLOT( setValue(int) ) ); the signal takes an integer as argument. In older Qt versions(older than Qt5), signals and slots must use exactly the same types, meaning that the implicit conversion may not occur.
https://forum.qt.io/topic/23302/connect-diferent-signals-and-slost-each-other/4

Related

Segmentation fault 11 when pass a Python tuple to C++ function with ctypes

I am trying to invoke some C++ functions in Python code with Python ctypes. I have two code files: one is core_lib.cpp, which defines a class and a member method; the other is demo.py, which instantiates the class and calls the member method.
core_lib.cpp is defined as below.
#include <iostream>
#include <tuple>
using namespace std;
class A {
private:
string _name;
tuple<int, int> _size;
public:
A() {
this->_name = "";
this->_size = make_tuple(1, 1);
cout << "Init values of _size: " << get<0>(this->_size) << ", " << get<1>(this->_size) << endl;
}
void set_size(int* size) {
int a = *size;
int b = *(size+1);
this->_size = make_tuple(a, b);
cout << "New values of _size: " << get<0>(this->_size) << ", " << get<1>(this->_size) << endl;
}
};
// bridge C++ to C
extern "C" {
A* create_A() {
return new A();
}
void set_size(A* a, int* size) {
a->set_size(size);
}
}
demo.py is defined as below.
from ctypes import *
import os
# load C++ lib
core_lib = cdll.LoadLibrary(os.path.abspath('test/stackoverflow/core_lib.so'))
class A(object):
def __init__(self):
self.a = core_lib.create_A()
def set_size(self, size):
core_lib.set_size(self.a, size)
if __name__ == "__main__":
asize = (3, 3)
size = (c_int * 2)(*asize)
a = A()
a.set_size(size)
To reproduce the issue, I list my steps here:
Compile core_lib.cpp:
g++ core_lib.cpp -fPIC -shared -std=c++11 -o core_lib.so
Run the python script: python demo.py
The Python version is 2.7.15, and runs on MacOS Mojave.
According to my investigation, the issue is caused by the code line in core_lib.cpp:
this->_size = make_tuple(a, b)
I tried to google the issue, but I didn't find an answer. I would appreciate any comment that would help understand the issue and how to fix it.
Define .argtypes and .restype for your functions. The default type is c_int (32-bit) and you are probably using an OS where pointers are 64-bit, truncating the A* return value.
core_lib.create_A.argtypes = None
core_lib.create_A.restype = c_void_p
core_lib.set_size.argtypes = [c_void_p,POINTER(c_int)]
core_lib.set_size.restype = None
c_void_p is sufficient for an opaque pointer. You can get better type checking by declaring a pointer to a class, and declaring the size pointer to be an array of two ints:
class A(Structure):
pass
core_lib.create_A.argtypes = None
core_lib.create_A.restype = POINTER(A)
core_lib.set_size.argtypes = POINTER(A),POINTER(c_int * 2)
core_lib.set_size.restype = None
If you have a choice, I recommend defining set_size as void set_size(A* a, int x, int y) so you can call as a.set_size(3,3) directly instead of creating a (c_int * 2)(3,3) to pass.

PyModule_GetDict not adding custom functions and globals to the generated dictionary (Python27)

I've followed all of the basic steps trying to get a python module loaded in c++, however it seems that when I try to get the dictionary of items in the script, it ignores my functions and globals that I wanted to use inside. when I iterate through the items, all I get are the builtins, file, package, path, name, and doc attributes of the script, and nothing else. I checked __name__ and it is coming up correctly ("test.py" is my py file's name and it returns "test" just fine). When I actually try to load my functions or globals (test, qa), the PyDict_GetItemString function returns NULL. What have I done wrong such that in tutorials this works fine, but in my test application, it doesn't work?
here is my Py script, maybe I've forgotten to do something that would allow my items to be seen?
qa = "hello test"
def test(a):
q = "hello world, I am " + a
#print q
return q
here is my C++ code as well, maybe I've forgotten something here?
#include <iostream>
#include <Python.h>
int main() {
Py_Initialize();
PyObject
*pName,
*pModule,
*pDict,
*pFunc,
*pArgs,
*pValue;
// get filename as a pystring
pName = PyString_FromString("test");
std::cout << std::endl << pName;
// Import module from filename
pModule = PyImport_Import(pName);
std::cout << std::endl << pModule;
// build the module's dict
pDict = PyModule_GetDict(pModule);
std::cout << std::endl << pDict << " " << PyDict_Size(pDict);
PyObject* keys = PyDict_Keys(pDict);
int s = PyList_Size(keys);
for (int i = 0; i < s; ++i) {
PyObject* item = PyList_GetItem(keys, i);
printf("\n");
printf(PyString_AsString(item));
}
PyObject* testvar = PyDict_GetItemString(pDict, "qa");
printf(PyString_AsString(testvar));
// get a function from the dict
pFunc = PyDict_GetItemString(pDict, "test");
std::cout << std::endl << pFunc;
// build the arg tuple
pArgs = PyTuple_New(1);
// create an argument
pValue = PyString_FromString("cee programme");
// set an argument
PyTuple_SetItem(pArgs, 0, pValue);
// call the function with the func and the args
PyObject* pResult = PyObject_CallObject(pFunc, pArgs);
// error checking
if (pResult == NULL) {
printf("\nis broek");
}
char* res = PyString_AsString(pResult);
// "destroy the interpreter"
Py_Finalize();
printf(res);
return 0;
}

Wrapping an opencv implementaion of an error level analysis algorithm using cython

i have implemented an error level analysis algorithm using c++(opencv version 2.4) and i want to build a python wrapper for it using cython.
I have read some part of the documentation of cython for c++ but it did not help me and moreover i did not find any extra information for implementing the wrapper online.
It would be really great if someone could guide me and help me solve this problem.
This is my code for which i want to build a pyhton wrapper:
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <vector>
// Control
int scale = 15,
quality = 75;
// Image containers
cv::Mat input_image,
compressed_image;
void processImage(int, void*)
{
// Setting up parameters and JPEG compression
std::vector<int> parameters;
parameters.push_back(CV_IMWRITE_JPEG_QUALITY);
parameters.push_back(quality);
cv::imwrite("lena.jpeg", input_image, parameters);
// Reading temp image from the disk
compressed_image = cv::imread("lena.jpeg");
if (compressed_image.empty())
{
std::cout << "> Error loading temp image" << std::endl;
exit(EXIT_FAILURE);
}
cv::Mat output_image = cv::Mat::zeros(input_image.size(), CV_8UC3);
// Compare values through matrices
for (int row = 0; row < input_image.rows; ++row)
{
const uchar* ptr_input = input_image.ptr<uchar>(row);
const uchar* ptr_compressed = compressed_image.ptr<uchar>(row);
uchar* ptr_out = output_image.ptr<uchar>(row);
for (int column = 0; column < input_image.cols; column++)
{
// Calc abs diff for each color channel multiplying by a scale factor
ptr_out[0] = abs(ptr_input[0] - ptr_compressed[0]) * scale;
ptr_out[1] = abs(ptr_input[1] - ptr_compressed[1]) * scale;
ptr_out[2] = abs(ptr_input[2] - ptr_compressed[2]) * scale;
ptr_input += 3;
ptr_compressed += 3;
ptr_out += 3;
}
}
// Shows processed image
cv::imshow("Error Level Analysis", output_image);
}
int main (int argc, char* argv[])
{
// Verifica se o número de parâmetros necessário foi informado
if (argc < 2)
{
std::cout << "> You need to provide an image as parameter" << std::endl;
return EXIT_FAILURE;
}
// Read the image
input_image = cv::imread(argv[1]);
// Check image load
if (input_image.empty())
{
std::cout << "> Error loading input image" << std::endl;
return EXIT_FAILURE;
}
// Set up window and trackbar
cv::namedWindow("Error Level Analysis", CV_WINDOW_AUTOSIZE);
cv::imshow("Error Level Analysis", input_image);
cv::createTrackbar("Scale", "Error Level Analysis", &scale, 100, processImage);
cv::createTrackbar("Quality", "Error Level Analysis", &quality, 100, processImage);
// Press 'q' to quit
while (char(cv::waitKey(0)) != 'q') {};
return EXIT_SUCCESS;
}
https://github.com/shreyneil/image_test/blob/master/ela.cpp
Contributions are welcome.
Thank you.
It isn't really clear what you hope to accomplish by this, but it's pretty easy to make the functions callable from Cython. Start by making some small changes to main - it will need renaming so that it no longer acts as the main function for a program, and since you only use the second command-line argument as a file name you should change it to:
void some_function(char* filename) {
// Read the image
input_image = cv::imread(filename);
// everything else the same
}
Then create your Cython wrapper cy_wrap.pyx. There are two parts to this. First you need to tell Cython about your two C++ functions (cdef extern from). Second you'll need to write a small wrapper function that can call these from Python:
cdef extern from "ela.hpp":
# you'll need to create ela.hpp with declarations for your two functions
void processImage(int, void*)
void some_function(char* filename)
# and Python wrappers
def processImagePy():
# since the parameters are ignored in C++ we can pass anything
processImage(0,NULL)
def some_functionPy(filename):
# automatic conversion from string to char*
some_function(filename)
Using this module you'll be able to call processImagePy and some_functionPy.
To compile it to a Python module you'll need to write a setup.py file. I suggest you follow the template given in the Cython documentation (which you have read, right?). Your source files will be cy_wrap.pyx and ela.cpp. You'll probably want to link to the OpenCV library. You'll need to specify language="c++"

How to use coordinates from an input file with prim's algorithm in order to create circles using pygraphics and C++?

I have looked at many many examples of Prim's Algorithm on here and Google and found no real answer to this question... Please excuse my structure of this problem. I'm terrible with how S/O prints things out.
I have an input file "SmallGraph.txt" that contains a set of coordinates and the number of vertices at the top:
9
50 100
100 150
200 150
300 150
350 100
300 50
200 50
100 50
150 100
I'm having a lot of trouble trying to figure out how to get these input items read so that my while loop will be able to print a "circle" for every vertice mentioned above so I can run Prim's algorithm for a minimum spanning tree.
What code I have so far of me attempting to get something printed out with a while loop. Also, a few classes to implement Prim's algorithm with those points I need to plot through python:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <cstring>
#include <math.h> /* pow() function */
// This line allows commonly-used functions to be used without specifying the
// library in which that function is defined. For instance, this line allows
// the use of "cout" rather than the full specification "cout"
using namespace std;
class SetOfIntegers
{
public:
// Constructor. Any setup operation you wish for the class.
SetOfIntegers()
{
members.clear();
} // end constructor
void add(int m) // Add members to set WITHOUT repetition
{
for (auto i : members)
{
if (i == m) return; // no addition of existing member
}
members.push_back(m);
}
int size() { return members.size(); }
void show() { for (auto i: members) cout << i << " "; cout << endl; }
bool isMember(int m)
{
//cout << "isMember(" << m << ") is ";
for (auto i : members)
{
if (i == m)
{
//cout << " true" << endl;
return true;
}
}
//cout << " false" << endl;
return false;
}
private:
vector<int> members;
};
//--------------------------------------------------------------------------
class Point
{
public:
// Constructor. Any setup operation you wish for the class.
Point()
{
x = 0; y = 0;
} // end constructor
Point(int a, int b, int id)
{
x = a; y = b; pointID = id;
} // end constructor
int getX() { return x; }
int getY() { return y; }
int getID() { return pointID; }
private:
int x = 0;
int y = 0;
int pointID = 0;
}; // end class Point
//--------------------------------------------------------------------------
class Edge
{
public:
// Constructor. Any setup operation you wish for the class.
Edge()
{
} // end constructor
Edge(Point ptA, Point ptB)
{
pointA = ptA;
pointB = ptB;
length = sqrt(pow(abs(pointA.getX() - pointB.getX() ), 2) + pow(abs(pointA.getY() - pointB.getY() ), 2) );
} // end constructor
Point getPtA() { return pointA; }
Point getPtB() { return pointB; }
double getLen() { return length; }
int getPtAID() { return pointA.getID(); }
int getPtBID() { return pointB.getID(); }
private:
Point pointA;
Point pointB;
double length;
}; // end class Edge
// NOTE: DO NOT declare with empty parentheses, as vector<Point> myPointvector();
vector<Point> myPointvector; // vector will expand as needed
vector<Edge> MinSpanTree;
// Pass arguments or parameters from command-line execution. argc is the count of
// those parameters, including the executable filename. argv[] is an array of the
// parameters.
int main (int argc, char *argv[])
{
string token;
int xValue, yValue;
ifstream fin;
int coordPairs; // number of coordinate pairs in the file
int ptX, ptY;
vector<Edge> unsortedEdgeVector;
vector<Edge> sortedEdgeVector;
int loopCounter;
int pointCounter = 0;
double MSTLength = 0.0;
// Check the number of arguments. Expected: filename of a file
if (argc != 2) // This check is often hardcoded
{ // If failure in parameters, offer advice for correction
cout << "\nThis program uses command-line argument.\n";
cout << "Usage: a.exe <filename>\n";
exit(0);
}
try // All lines within this block are part of the same exception handler
{
fin.open(argv[1]);
}
catch (exception& ex)
{
cout << ex.what(); // display standard explanation of the exception
exit(0); // exit the program
}
// Read from the file, one token at a time. If the type of token is known, it
// can be read into a corresponding variable type, such as
// in >> x; // Read the first item into an integer variable x.
// in >> str; // Read the next item into a string variable str.
//for (int i = 0; 1 != 10; i++) {
// fin >> ptX[2] >> ptY[2];
//}
//cout << ptX << endl;
// This line provides the graphic window setup.
cout << "800 600 white" << endl;
fin >> coordPairs;
while (fin >> ptX)
{
// Do something with the element read from the file
cout << ptX << endl;
fin >> ptY;
cout << ptY << endl;
cout << "circle " << ptX << " " << ptY << " " << 20 << " seagreen" << endl;
/*
Point dummyPoint(ptX, ptY, pointCounter++);
myPointvector.push_back(dummyPoint); // vector will expand as needed
cout << "Now myPointvector has size " << myPointvector.size() << endl;
*/
} // end while
fin.close();
}
As you can see... I have a while loop in my main function that is attempting to create a "circle" based on ptX and ptY. That's what I'm having trouble with.. How do I read from this input file in order to get these points and get them to create a circle through python? If you notice.. I've attempted a for loop that is currently commented out for reading the file.
I was using the wrong command for requesting information from the input file. I was using the commands:
g++ -std=c++11 PrimMSTAlgor.cpp (Compile the code)
a PrimMSTAlgor.cpp > PrimData.dat (Put data into primData.dat from the .cpp file)
python BearPlot.py PrimData.dat (use python to apply graphics)
The second command is incorrect. I need to use the .txt file as the argument for "a" (the execution).
a SmallGraph.txt > PrimData.dat
What I have is already set up to put the input into the .dat file this way, I just couldn't see it...

calling python function with parameters from C++

I created embedded python interpreter which is calling a function, that has 3 parameters. I successfully managed to do this for function without parameters, but when I execute PyObject_CallObject the program crashes with SEGFAULT:
#0 0x00007ffff79c3a25 in PyEval_EvalCodeEx () from /usr/lib/libpython3.2mu.so.1.0
#1 0x00007ffff79c42bf in ?? () from /usr/lib/libpython3.2mu.so.1.0
#2 0x00007ffff79c730a in PyObject_Call () from /usr/lib/libpython3.2mu.so.1.0
#3 0x00000000004f3f31 in Huggle::Python::PythonScript::Hook_SpeedyFinished(Huggle::WikiEdit*, bool) ()
The source code of call is:
void PythonScript::Hook_SpeedyFinished(WikiEdit *edit, bool successfull)
{
if (edit == nullptr)
return;
if (this->ptr_Hook_SpeedyFinished != nullptr)
{
HUGGLE_DEBUG("Calling hook Hook_SpeedyFinished #" + this->Name, 2);
// let's make a new list of params
PyObject *args = PyTuple_New(3);
PyObject *page_name = PyUnicode_FromString(edit->Page->PageName.toUtf8().data());
PyObject *user_name = PyUnicode_FromString(edit->User->Username.toUtf8().data());
PyObject *success;
if (!successfull)
successfull = PyUnicode_FromString("fail");
else
successfull = PyUnicode_FromString("success");
if (PyTuple_SetItem(args, 0, page_name))
HUGGLE_DEBUG("Failed to pass page_name to tuple #hook_speedy_finished", 3);
if (PyTuple_SetItem(args, 1, user_name))
HUGGLE_DEBUG("Failed to pass user to tuple #hook_speedy_finished", 3);
if (PyTuple_SetItem(args, 2, success))
HUGGLE_DEBUG("Failed to pass success to tuple #hook_speedy_finished", 3);
PyObject_CallObject(this->ptr_Hook_SpeedyFinished, args);
HUGGLE_DEBUG("finished", 1);
}
}
Full source code of this .cpp file is https://github.com/huggle/huggle3-qt-lx/blob/master/huggle/pythonengine.cpp
What is wrong? Is this even proper way to call the function? I am following https://docs.python.org/3/c-api/object.html and https://docs.python.org/2/c-api/tuple.html
Here is an example from the python documentation.
PyObject *arglist;
...
arglist = Py_BuildValue("(l)", eventcode);
result = PyObject_CallObject(my_callback, arglist);
Py_DECREF(arglist);
if (result == NULL)
return NULL; /* Pass error back */
/* Here maybe use the result */
Py_DECREF(result);
It seems to me you should take care of the refcount.
https://docs.python.org/3.0/extending/extending.html#calling-python-functions-from-c
Segmentation fault is discussed here.
Calling python method from C++ (or C) callback

Categories

Resources