I was wondering if I could get some help. Say I've got the following function to serialize an object:
PyObject * CKKSwrapper::SerializeContext() {
std::string s;
std::ostringstream os(s);
Serial::Serialize(m_cc, os, SerType::BINARY);
const std::string tmp = os.str();
const char *msg = tmp.c_str();
std::cout << "Length of context: " << tmp.length() << "\n";
return PyBytes_FromString(msg);
}
The Boost module file has
BOOST_PYTHON_MODULE (pycrypto) {
class_<pycrypto::CKKSwrapper>("CKKSwrapper")
.def("SerializeContext", &pycrypto::CKKSwrapper::SerializeContext,
return_value_policy<manage_new_object>());
where I am managing the object.
However, when I call the method in Python, I get a None object, and the output is
import pycrypto
a = pycrypto.SerializeContext()
a is None and I get Length of context: X to my console
Related
I am trying to use the boost.python library in order to get data from the Python skyfield API, but I am having trouble printing out the data. The program runs, but I get this error: "Error in Python: <class 'TypeError'>: 'NoneType' object is not callable"
The correct output should show something like this:
10h 47m 56.24s
+09deg 03' 23.1"
2.33251 au
I am using the first code example from this website as a reference: https://rhodesmill.org/skyfield/
If you have any ideas on how to get the data to correctly output, please let me know!
Here is my code so far:
#include <iostream>
#include <boost/python.hpp>
#include <Python.h>
namespace py = boost::python;
std::string parse_python_exception();
int main()
{
Py_Initialize(); //Initializes the Python interpreter
//Imports the __main__ module and extracts the namespace
//This creates a blank 'canvas' upon which we can call Python code
py::object main_module = py::import("__main__");
//Loads the dictionary object from the main module
py::object main_namespace = main_module.attr("__dict__");
try
{
//Imports
py::exec("from skyfield.api import load");
py::object skyfield_mod = py::import("skyfield.api");
py::object skyfield_load = skyfield_mod.attr("load");
py::object skyfield_load_timescale = skyfield_load.attr("timescale");
py::exec("print('This program computes the current position of Mars in the sky')", main_namespace);
py::object ts = skyfield_load_timescale();
py::object ts_now = ts.attr("now");
py::object t = ts_now();
py::object planets = skyfield_load("de421.bsp");
py::object earth = planets["earth"];
py::object mars = planets["mars"];
py::object earth_at = earth.attr("at");
py::object earth_at_observe = earth_at(t).attr("observe");
py::object m_earth_at_observe = earth_at_observe(mars);
py::object astrometric = m_earth_at_observe;
py::object ra, dec, distance = astrometric.attr("radec");
py::object m_ra = ra();
py::object m_dec = dec();
py::object m_distance = distance();
py::exec("print(m_ra)", main_namespace);
}
catch (boost::python::error_already_set const&)
{
std::string perror_str = parse_python_exception();
std::cout << "Error in Python: " << perror_str << std::endl;
}
}
// Parses the value of the active python exception
// NOTE SHOULD NOT BE CALLED IF NO EXCEPTION
std::string parse_python_exception() {
PyObject* type_ptr = NULL, * value_ptr = NULL, * traceback_ptr = NULL;
// Fetch the exception info from the Python C API
PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
// Fallback error
std::string ret("Unfetchable Python error");
// If the fetch got a type pointer, parse the type into the exception string
if (type_ptr != NULL) {
py::handle<> h_type(type_ptr);
py::str type_pstr(h_type);
// Extract the string from the boost::python object
py::extract<std::string> e_type_pstr(type_pstr);
// If a valid string extraction is available, use it
// otherwise use fallback
if (e_type_pstr.check())
ret = e_type_pstr();
else
ret = "Unknown exception type";
}
// Do the same for the exception value (the stringification of the exception)
if (value_ptr != NULL) {
py::handle<> h_val(value_ptr);
py::str a(h_val);
py::extract<std::string> returned(a);
if (returned.check())
ret += ": " + returned();
else
ret += std::string(": Unparseable Python error: ");
}
// Parse lines from the traceback using the Python traceback module
if (traceback_ptr != NULL) {
py::handle<> h_tb(traceback_ptr);
// Load the traceback module and the format_tb function
py::object tb(py::import("traceback"));
py::object fmt_tb(tb.attr("format_tb"));
// Call format_tb to get a list of traceback strings
py::object tb_list(fmt_tb(h_tb));
// Join the traceback strings into a single string
py::object tb_str(py::str("\n").join(tb_list));
// Extract the string, check the extraction, and fallback in necessary
py::extract<std::string> returned(tb_str);
if (returned.check())
ret += ": " + returned();
else
ret += std::string(": Unparseable Python traceback");
}
return ret;
}
I use cpp to call python function, I have compiled the program without errors, but why can not I see the print result in python function.
here is the cpp codes:
#include<python2.7/Python.h>
....
using namespace std;
int main()
{
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("import os");
PyRun_SimpleString("import string");
PyRun_SimpleString("sys.path.append('./')");
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject * pClass = NULL;
PyObject * pInstance = NULL;
pModule = PyImport_ImportModule("download");
if(!pModule)
{
std::cout << "there is no this file." << std::endl;
}
pFunc= PyObject_GetAttrString(pModule, "geturl");
if(!pFunc)
{
std::cout << "there is no this func." << std::endl;
}
std::string url = "www";
PyObject* args = Py_BuildValue("ss", url.c_str());
PyEval_CallObject(pFunc, args);
Py_DECREF(pFunc);
Py_Finalize();
return 0;
}
here is the download.py file in the same dir
def geturl(url):
print(url)
print("hello")
here is result, without errors nor print:
root#cvm-172_16_20_84:~/klen/test/cpppython # g++ t.cpp -o printurl -lpython2.7
root#cvm-172_16_20_84:~/klen/test/cpppython # ./printurl
root#cvm-172_16_20_84:~/klen/test/cpppython #
How can I see the print, has the function geturl run successfully? Thanks
The PyEval_CallObject function is encountering a Python exception before it reaches your print statements. Adding error handling to this call (call PyErr_Print on NULL return value) will show the exception being raised:
TypeError: geturl() takes exactly 1 argument (2 given)
The root cause is the format string:
Py_BuildValue("ss", url.c_str());
You are creating a tuple of two values and passing that as the arguments geturl(). You need to pass a tuple with only one value. You are also invoking undefined behavior here because you haven't provided a second string pointer.
Resolve the issue by passing a tuple with only one value:
Py_BuildValue("(s)", url.c_str());
This question follows this one.
I use CFFI to create a DLL and I call it from a C++ application. I was questioning myself to find how to release memory allocated by the DLL and I follow the idea mention by #metal in its answer.
Here is now my Python code:
import cffi
ffibuilder = cffi.FFI()
ffibuilder.embedding_api('''
char* get_string();
void free_char(char*);
''')
ffibuilder.set_source('my_plugin', '')
ffibuilder.embedding_init_code('''
from my_plugin import ffi, lib
#ffi.def_extern()
def get_string():
val = "string"
return lib.strdup(val.encode())
#ffi.def_extern()
def free_char(ptr):
lib.free(ptr)
''')
ffibuilder.cdef('''
char *strdup(const char *);
void free(void *ptr);
''')
ffibuilder.compile(target='my-plugin.*', verbose=True)
And my C++ code:
#include <iostream>
#include <windows.h>
typedef char* (__stdcall *get_string_t)();
typedef void (__stdcall *free_char_t)(char*);
int main()
{
HINSTANCE hGetProcIDDLL = LoadLibrary("my-plugin.dll");
if (!hGetProcIDDLL) {
std::cout << "could not load the dynamic library" << std::endl;
return -1;
}
get_string_t get_string = (get_string_t)GetProcAddress(hGetProcIDDLL, "get_string");
if (!get_string) {
std::cout << "could not locate the function" << std::endl;
return -1;
}
free_char_t free_char = (free_char_t)GetProcAddress(hGetProcIDDLL, "free_char");
if (!free_char) {
std::cout << "could not locate the function" << std::endl;
return -1;
}
for(int i = 0; i < 25000000; i++)
{
char* val = NULL;
val = get_string();
if(i % 10000 == 0)
{
std::cout << "Value " << i << " = " << val << std::endl;
}
if(val)
free_char(val);
}
std::cout << "End" << std::endl;
return 0;
}
I get this result:
Value 0 = string
Value 10000 = string
Value 20000 = string
Value 30000 = string
Value 40000 = string
Value 50000 = string
Value 60000 = string
Value 70000 = string
Value 80000 = string
Value 90000 = string
Value 100000 = string
Value 110000 = string
Value 120000 = string
Value 130000 = string
Value 140000 = string
Value 150000 = string
Value 160000 = string
Value 170000 = string
Value 180000 = string
Value 190000 = string
Value 200000 = string
Value 210000 = string
Value 220000 = string
Value 230000 = string
Value 240000 = string
Value 250000 = string
From cffi callback <function get_string at 0x03470810>:
MemoryError: Stack overflow
From cffi callback <function get_string at 0x03470810>:
From cffi callback <function get_string at 0x03470810>:
From cffi callback <function get_string at 0x03470810>:
From cffi callback <function get_string at 0x03470810>:
What does this error mean? I don't have memory problem because I release memory with my new free_char function. By the way, if I remove the call to free_char I can make all the loops (but the memory is not release).
From documentation of cffi :
The recommended C compiler compatible with Python 2.7 is this one:
http://www.microsoft.com/en-us/download/details.aspx?id=44266
...
For Python 3.4 and beyond:
https://www.visualstudio.com/en-us/downloads/visual-studio-2015-ctp-vs
Then you should either downgrade python or upgrade visual-studio.
Within my c++ program, I have a class called "pEngine" that is supposed to handle interaction between my program and a python session. There can be any number of these pEngines and each one needs to be working individually since during their initialization they each execute a different python script (unknown till run time).
Currently I have each script defining a main function that takes a single variable, the payload, and depending on the script produces a different output which my program pipes back. The pEngine is then deleted. For a single pEngine my code works great allowing me to preload data in the script for the function, then call it later when needed.
My problem is that since it closes its session, all other pEngines are effected. I cannot load multiple scripts into the same session since they all have have the same prototype for their main function. What I was looking for was a way to have a python session instance object that is separate and individual so I could run commands against it.
My pEngine.h
#include <cstring>
#include "Engine.h"
#include "/usr/include/python2.7/Python.h"
#ifndef PENGINE_H
#define PENGINE_H
class pEngine : public Engine
{
public:
pEngine();
~pEngine();
std::string execute(const std::string& cmd);
int setwd(const std::string& dir);
int source(const std::string& script);
std::string main(const std::string& payload);
private:
PyObject *pModule;
PyObject *stdOut;
};
#endif /* PENGINE_H */
My pEngine.cpp
#include "pEngine.h"
pEngine::pEngine()
{
/* Start a python session and create a class to capture the standard out
text. Define it as the standard out location and run this code in the
session. Then store a pointer to this python object to extract returned
values. */
Py_Initialize();
pModule = PyImport_AddModule("__main__"); //create main module
std::stringstream pythonOutputs;
pythonOutputs << "import sys" << "\n"
<< "class CatchStdOut:" << "\n"
<< "\t" << "def __init__(self):" << "\n"
<< "\t" << "\t" << "self.value = ''" << "\n"
<< "\t" << "def write(self, txt):" << "\n"
<< "\t" << "\t" << "self.value += txt" << "\n"
<< "\t" << "def clear(self):" << "\n"
<< "\t" << "\t" << "self.value = ''" << "\n"
<< "StdOut = CatchStdOut()" << "\n"
<< "sys.stdout = StdOut";
PyRun_SimpleString((pythonOutputs.str()).c_str());
stdOut = PyObject_GetAttrString(pModule,"StdOut");
}
pEngine::~pEngine(){
Py_Finalize();
}
std::string pEngine::execute(const std::string& cmd)
{
/* Place cmd in try except statement to protect against unknown errors. */
std::stringstream pString;
pString << "program_status = 200" << "\n"
<< "StdOut.clear()" << "\n"
<< "try:" << "\n"
<< "\t" << cmd << "\n"
<< "except Exception as e:" << "\n"
<< "\t" << "program_status = 400" << "\n"
<< "\t" << "print(e)";
/* Run Command against the interpreter and store returned answer. */
PyRun_SimpleString( (pString.str()).c_str() );
PyErr_Print(); //make python print
//returned payload
std::string RPL =
PyString_AsString(PyObject_GetAttrString(stdOut,"value"));
/* Clear the payload from the capture object and run a command to fill in
the status. */
std::stringstream statusCollector;
statusCollector << "StdOut.clear()\n"
<< "print program_status";
/* Run command and extract status. */
PyRun_SimpleString( (statusCollector.str()).c_str() );
PyErr_Print();
//status
std::string PST =
PyString_AsString(PyObject_GetAttrString(stdOut,"value"));
if (!RPL.empty() && RPL[RPL.length()-1] == '\n') RPL.erase(RPL.length()-1);
if (!PST.empty() && PST[PST.length()-1] == '\n') PST.erase(PST.length()-1);
/* Set Program status and return the payload from the python session. */
program_status = std::stoi( PST );
return RPL;
}
std::string pEngine::main(const std::string& payload)
{
std::string returned = execute( "print main("+toEscapedString(payload)+")");
Py_Finalize();
if( program_status != 200 ) status = Engine::ENG_EXECUTE_ERROR;
return returned;
}
int pEngine::setwd(const std::string& dir)
{
std::string pString = "import os\n\tos.chdir(" + toEscapedString(dir) + ")";
execute( pString );
if( program_status != 200 ) status = Engine::ENG_SESSION_ERROR;
return status;
}
int pEngine::source(const std::string& script)
{
std::string pString = "execfile(" + toEscapedString(script) + ")";
execute( pString );
if( program_status != 200 ) status = Engine::ENG_SESSION_ERROR;
return status;
}
I have the C code which works and returns good properties:
int main(int argc, char** argv) {
CvCapture *capture = NULL;
const char* filename = "foo.mov";
capture = cvCreateFileCapture(filename);
int w = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
int h = (int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
std::cout << "Width: " << w << std::endl;
std::cout << "Height: " << h << std::endl;
but the Python equivalent just returns 0 for everything:
import cv2
capture = cv2.VideoCapture('foo.mov')
print capture.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)
This returns 0.0
Any ideas?
check the open cv version in python and in c :
from cv2 import version
version
and using CV_VERSION macro.
what is the output for
capture.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)
Are the python and foo.mov located on the same dir?