How to convert PyObject to UTF-8 string? - c++

I'm trying to pass a string value to a Python function and get a utf-8 string value. The function retrieves Japanese characters and returns characters in another language.
I used ctypes.windll.user32.MessageBoxW in the Python script and made sure there is no problem with the Python function. And I tried a simple function like return 'hello world' to test. I also checked every function with assert. I guess the problem starts with PyBytes_AsString. It always returns DB DB DB DB DB DB DB... (in hex). But I don't know how to fix this.
char* result;
PyObject* module, *func, *arg, *ret, *value;
Py_Initialize();
PyObject* sysPath = PySys_GetObject("path");
PyObject* path = PyUnicode_FromString(".");
PyList_Append(sysPath, path);
module = PyImport_ImportModule("test");
if (module != 0)
{
const wchar_t* w = L"翻訳テスト";
func = PyObject_GetAttrString(module, "translate");
arg = PyTuple_New(1);
value = PyUnicode_FromWideChar(w, wcslen(w));
PyTuple_SetItem(arg, 0, value);
ret = PyObject_CallObject(func, arg);
PyObject* repr = PyObject_Repr(ret);
PyObject* str = PyUnicode_AsEncodedString(repr, "utf-8", "strict");
result = PyBytes_AsString(str);
Py_DECREF(repr);
Py_DECREF(str);
Py_DECREF(module);
Py_DECREF(func);
Py_DECREF(arg);
Py_DECREF(ret);
fstream file("text.txt", std::ios::out);
file << result;
file.close();
}
Py_Finalize();

result = PyBytes_AsString(str) returns a pointer to the internal buffer of str, so don't Py_DECREF(str) before you write result to the file.

Related

How to pass a callback to EM_ASM for c++?

I do not know how to pass the value asynchronously to EM_ASM, here's how I try to do it (but JS says it's not a function):
const auto testFunc = [] (const char* data)
{
printf("data: %s\n", data);
}
EM_ASM_(
{
var funcResult = ($0);
var text = "data";
var lengthBytes = lengthBytesUTF8(text) + 1;
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(text, stringOnWasmHeap, lengthBytes);
// exception thrown: TypeError: funcResult is not a function
funcResult(stringOnWasmHeap);
}, testFunc);
The documentation says that you can use a function (em_str_callback_func) of the em_str_callback_func type. But it doesn't say how to use it.
https://emscripten.org/docs/api_reference/emscripten.h.html
I don't know about passing callbacks, but if what you want to do is to return a value from JS, then the docs have such an example: you have to use EM_ASM_INT instead:
int x = EM_ASM_INT({
console.log('I received: ' + $0);
return $0 + 1;
}, 100);
printf("%d\n", x);
The API reference has another example for returning a string:
char *str = (char*)EM_ASM_INT({
var jsString = 'Hello with some exotic Unicode characters: Tässä on yksi lumiukko: ☃, ole hyvä.';
var lengthBytes = lengthBytesUTF8(jsString)+1;
// 'jsString.length' would return the length of the string as UTF-16
// units, but Emscripten C strings operate as UTF-8.
var stringOnWasmHeap = _malloc(lengthBytes);
stringToUTF8(jsString, stringOnWasmHeap, lengthBytes);
return stringOnWasmHeap;
});
printf("UTF8 string says: %s\n", str);
free(str); // Each call to _malloc() must be paired with free(), or heap memory will leak!
Once you have the value in C you can just call your testfunc directly.

cython create string with nogil

I would like to create a c++ string in a nogil function in a file that would be cimported via pxd. If I define, string output = "" or string output = string("blah"), this uses the python interpreter. Is there a way to define the a string so that the compiler writes in the cython cpp file:
std::string val = "blah";
Basically have this:
from libcpp.string cimport string
cdef string my_func() nogil:
cdef:
string output = "blah"
....
return output
%%cython -a
#distutils: language = c++
from libcpp.string cimport string
cdef string my_func() nogil:
cdef:
char* c_str = 'blah'
string output = <string>(c_str)
return output
def py_call():
return my_func()
Then calling py_call() gives b'blah', i.e. a bytes object.
EDIT: Here's the generated C++ code:
+08: char* c_str = 'blah'
__pyx_v_c_str = ((char *)"blah");
+09: string output = <string>(c_str)
__pyx_v_output = ((std::string)__pyx_v_c_str);
So it literally casts char* to std::string.
An alternative is then to invoke the constructor from char*:
cdef:
char* c_str = 'blah'
string output = string(c_str)
which generates
+08: char* c_str = 'blah'
__pyx_v_c_str = ((char *)"blah");
+09: string output = string(c_str, 4)
try {
__pyx_t_1 = std::string(__pyx_v_c_str, 4);
} catch(...) {
#ifdef WITH_THREAD
PyGILState_STATE __pyx_gilstate_save = PyGILState_Ensure();
#endif
__Pyx_CppExn2PyErr();
#ifdef WITH_THREAD
PyGILState_Release(__pyx_gilstate_save);
#endif
__PYX_ERR(0, 9, __pyx_L1_error)
}
__pyx_v_output = __pyx_t_1;
which looks better.

Calling a Python function within a C++ program

I have a real simple Python function:
def myfunc(x):
return 2.0 * x
I want to send this function to a C++ program and call it so I have done this:
#include "Python.h"
static PyObject *execMyPyFunc(PyObject *self, PyObject *args) {
PyObject *Fx, *pyresult;
double x;
PyArg_ParseTuple(args, "dO", &x, &Fx);
pyresult = PyObject_CallFunction(Fx, "d", x);
return pyresult;
}
static PyMethodDef C_API_TestMethods[] = {
{"execMyPyFunc", execMyPyFunc, METH_VARARGS, "Add documentation here.."},
{NULL, NULL}
};
PyMODINIT_FUNC initC_API_Test(void) {
Py_InitModule("C_API_Test", C_API_TestMethods);
}
My Python program works correctly:
from C_API_Test import execMyPyFunc
def myfunc(x):
return 2.0 * x
fx = execMyPyFunc(1.28,myfunc)
print fx
What I would like to do though is to somehow get the pointer from my Python function (PyObject *Fx) and pass this to a C++ function expecting: double(*fx)(double). Does anyone know how to do this (if possible)? I tried to initialize double(*cFx)(double) and cast my Python function as cFx = (double(*)(double))Fx but this does not work. Any ideas?
You aren't going to be able to simply cast a Python function to C like that.
Instead pass the PyObject function pointer, call the function, and convert to C double. This code will return -1 on failure.
static double cFx(PyObject *fx, double x){
PyObject *pyresult = PyObject_CallFunction(fx, "d", x);
if (pyresult == NULL) return -1;
double cppresult = PyFloat_AsDouble(pyresult);
Py_DECREF(pyresult);
if (PyErr_Occurred()) return -1;
return cppresult;
}
Important part of this is to decrement the reference count to the return value of PyObject_CallFunction since you aren't passing it off to the Python interpreter to deal with.

C/C++ embedding python module PIL, the python function want to return all pixel data, but i why can't?

add c/c++ code embedding python. all problem is in c code, I don't known how to get the pixel value.
python code:
import Image
format = ""
mode = ""
size = ""
data = list()
def getImage(file):
im = Image.open(file)
global format
global mode
global size
global data
format = im.format
mode = im.mode
size = im.size
width, height = im.size
for x in range(0, height):
for y in range(0, width):
data.append(im.getpixel((x,y)))
return None
in C/C++ code
My get the data length is 0. Any problems of the two for loop?
void loadImage(char *file) {
Image* img = NULL;
Py_Initialize();
if ( !Py_IsInitialized() ) {
std::cerr<<"Python initalize failed.\n";
return NULL;
}
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyObject *pName, *pModule, *pFunc, *pArgs;
pName = PyString_FromString("loadImage");
pModule = PyImport_Import(pName);
Py_DECREF(pName);
if ( !pModule ) {
PyErr_Print();
std::cerr<<"import loadImage module faild, please confirm where the file 'loadImage.py' is.\n";
return NULL;
}
pFunc = PyObject_GetAttrString(pModule, "getImage");
if ( !pFunc ) {
PyErr_Print();
std::cerr<<"Can't find method getImage in loadImage module.\n";
return NULL;
}
pArgs = PyTuple_New(1);
PyTuple_SetItem(pArgs, 0, Py_BuildValue("s", file));
PyObject_CallObject(pFunc, pArgs);
PyObject *pFormat, *pMode, *pSize, *pData, *pSeq, *pPixel;
pFormat = PyObject_GetAttrString(pModule, "format");
pMode = PyObject_GetAttrString(pModule, "mode");
pSize = PyObject_GetAttrString(pModule, "size");
if ( !PyTuple_Check(pSize) ) {
std::cerr<<"pSize is not tupple object.\n";
return NULL;
}
pData = PyObject_GetAttrString(pModule, "data");
if ( !pData ) {
std::cerr<<"pData is null.\n";
return NULL;
}
if ( !PyList_Check(pData) ) {
std::cerr<<"pData is not list object.\n";
return NULL;
}
int n = PyList_GET_SIZE(pData);
std::cerr<<n<<"\n";
Py_DECREF(pData);
Py_DECREF(pFunc);
Py_DECREF(pModule);
Py_DECREF(pArgs);
std::cerr<<"Py_DECREF over.\n";
}
I get the lenght of pData(is n) is 0.
Well, your code can literally be replaced with a single line:
data = list(Image.open(file).getdata())
The getdata method of Image objects returns the pixels packed into a list, line-by-line. If you need them in column-major order (as you are doing), apply .transpose with the appropriate arguments first. The result will still be substantially faster and simpler than iterating over all the pixels.
You aren't checking the return value from PyObject_CallObject. It might have returned NULL (Python exception), and consequently failed to modify the data list.
You should check every Python API call you make, since exception handling is critically important to making the interpreter work correctly.
If you do get a NULL, you can call PyErr_Print() to get the traceback printed out to stderr (cerr).
The Python code you run by calling PyObject_CallObject is probably throwing an exception.
NULL means an exception was thrown. You can use various python api functions to get at
the actual error: http://docs.python.org/c-api/exceptions.html. This is probably the simplest.
if( PyObject_CallObject(pFunc, pArgs ) == NULL )
{
// Print the exception (a traceback may or may not be available)
PyErr_Print();
// Do any cleanup...
// Always return NULL after a python api function returns NULL.
return NULL;
}
The problem may caused by the python version 2.7 in my computer. I changed to python 3.2, all code can got ideal return.

What's the most efficient way to do recursive XPath queries using libxml2?

I've written a C++ wrapper function for libxml2 that makes it easy for me to do queries on an XML document:
bool XPathQuery(
const std::string& doc,
const std::string& query,
XPathResults& results);
But I have a problem: I need to be able to do another XPath query on the results of my first query.
Currently I do this by storing the entire subdocument in my XPathResult object, and then I pass XPathResult.subdoc into the XPathQuery function. This is awfully inefficient.
So I'm wondering ... does libxml2 provide anything that would make it easy to store the context of an xpath query (a reference to a node, perhaps?) and then perform another query using that reference as the xpath root?
You should reuse the xmlXPathContext and just change its node member.
#include <stdio.h>
#include <libxml/xpath.h>
#include <libxml/xmlerror.h>
static xmlChar buffer[] =
"<?xml version=\"1.0\"?>\n<foo><bar><baz/></bar></foo>\n";
int
main()
{
const char *expr = "/foo";
xmlDocPtr document = xmlReadDoc(buffer,NULL,NULL,XML_PARSE_COMPACT);
xmlXPathContextPtr ctx = xmlXPathNewContext(document);
//ctx->node = xmlDocGetRootElement(document);
xmlXPathCompExprPtr p = xmlXPathCtxtCompile(ctx, (xmlChar *)expr);
xmlXPathObjectPtr res = xmlXPathCompiledEval(p, ctx);
if (XPATH_NODESET != res->type)
return 1;
fprintf(stderr, "Got object from first query:\n");
xmlXPathDebugDumpObject(stdout, res, 0);
xmlNodeSetPtr ns = res->nodesetval;
if (!ns->nodeNr)
return 1;
ctx->node = ns->nodeTab[0];
xmlXPathFreeObject(res);
expr = "bar/baz";
p = xmlXPathCtxtCompile(ctx, (xmlChar *)expr);
res = xmlXPathCompiledEval(p, ctx);
if (XPATH_NODESET != res->type)
return 1;
ns = res->nodesetval;
if (!ns->nodeNr)
return 1;
fprintf(stderr, "Got object from second query:\n");
xmlXPathDebugDumpObject(stdout, res, 0);
xmlXPathFreeContext(ctx);
return 0;
}