Calling a python method from C/C++, and extracting its return value
As explained before, using PyRun_SimpleString seems to be a bad idea.
You should definitely use the methods provided by the C-API (http://docs.python.org/c-api/).
Reading the introduction is the first thing to do to understand the way it works.
First, you have to learn about PyObject that is the basic object for the C API. It can represent any kind of python basic types (string, float, int,...).
Many functions exist to convert for example python string to char* or PyFloat to double.
First, import your module :
PyObject* myModuleString = PyString_FromString((char*)"mytest");
PyObject* myModule = PyImport_Import(myModuleString);
Then getting a reference to your function :
PyObject* myFunction = PyObject_GetAttrString(myModule,(char*)"myabs");
PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(2.0));
Then getting your result :
PyObject* myResult = PyObject_CallObject(myFunction, args)
And getting back to a double :
double result = PyFloat_AsDouble(myResult);
You should obviously check the errors (cf. link given by Mark Tolonen).
If you have any question, don't hesitate. Good luck.
Call C++ function from python and get return value
If you use the readelf -Ws on your so file, it will give you items inside your so library:
FUNC GLOBAL DEFAULT 12 _Z9getStringB5cxx11v
You will see that your function is in fact there, it just has a mangled name.
So proper name for calling ctype on the library would be _Z9getStringB5cxx11v().
However there are still few things wrong with it.
Mark your method as an extern to let compiler know it has external linkage:
extern string getString()
Alternatively if you want to use it as getString() you can mark it as extern "C" which will disable c++ mangler
extern "C" string getString()
But in either case I think you will find that you have some memory problems. I think the proper way would be to return c style pointer to a character array and memory manage it yourself, something like this should work:
strfunc.cpp:
#include <iostream>
#include <string>
using namespace std;
char hostname[] = "test.stack.com";
extern "C" char * getString()
{
return hostname;
}
strfunc.py:
#!/usr/bin/env python
from ctypes import *
test=cdll.LoadLibrary("./strfunc.so")
test.getString.restype=c_char_p
print(test.getString())
In case of string I think you need to figure out how to manage memory and return types properly to let know to the python that you are actually passing string. It might be doable but not so easy as the above.
Python C API: problems with calling python c method in c
You must create a PyTuple as second argument of your own function(st_div_r)!
There are 2 main ways to do that!
First Way
PyObject *first_list = PyList_GetItem(pList, 0)
//PyObject *divider = Py_BuildValue("d", d)
//PyObject *tuple_with_list_and_divider = Py_BuildValue("(Od)", first_list, divider);
PyObject *tuple_with_list_and_divider = Py_BuildValue("(Od)", first_list, d);
PyObject *list_after_division = st_div_r(pList, tuple_with_list_and_divider)
PyList_SetItem(pList , 0, list_after_division);
Second Way
PyObject *first_list = PyList_GetItem(pList, 0)
PyObject *divider = Py_BuildValue("d", d)
PyObject *tuple_with_list_and_divider = PyTuple_New(2);
PyTuple_SetItem(tuple_with_list_and_divider, 0, first_list);
PyTuple_SetItem(tuple_with_list_and_divider, 1, divider);
PyObject *list_after_division = st_div_r(pList, tuple_with_list_and_divider)
PyList_SetItem(pList , 0, list_after_division);
In first example I forgot that Py_BuildValue converts d to Py_Double.
Sorry for my Bad English!
Extracting value from Python after it's embedded in C++
I have actually figured out how to do that myself. There is no need to use eval()
in order to extract the result of the execution of the function. Instead, you can do the following:
#include <Python.h>
#include <iostream>
int main() {
// Initialize Python
Py_Initialize();
// Create a function
PyRun_SimpleString("f = lambda x: x * 2 - 3");
// Import __main__ where the f is stored
PyObject *main = PyImport_ImportModule("__main__");
PyObject *function = PyObject_GetAttrString(main, "__function");
// Create an argument tuple for the function
PyObject * args = PyTuple_New(1);
PyObject * first_argument = PyInt_FromLong(10);
PyTuple_SetItem(args, 0, first_argument);
// Call the function and get its result
PyObject * result = PyObject_CallObject(function, args);
// Output the result
cout << PyInt_AsLong(result) << endl;
// Destroy Python frame
Py_Finalize();
}
However, I am still curious why eval
did not work as shown in my original question
Calling python hello world function from C, parsing string arguments
The sample code is parsing the arguments as integers, buy you've passed a string. atoi("world")
returns 0, so that's the integer you get:
/* Create tuple of the correct length for the arguments. */
pArgs = PyTuple_New(argc - 3);
for (i = 0; i < argc - 3; ++i) {
/* Convert each C argv to a C integer, then to a Python integer. */
pValue = PyInt_FromLong(atoi(argv[i + 3]));
if (!pValue) {
Py_DECREF(pArgs);
Py_DECREF(pModule);
fprintf(stderr, "Cannot convert argument\n");
return 1;
}
/* iValue reference stolen here: */
/* Store the Python integer in the tuple at the correct offset (i) */
PyTuple_SetItem(pArgs, i, pValue);
}
Change the conversion line to the following to handle any string:
pValue = PyString_FromString(argv[i + 3]);
Running and obtaining results of a python program in C
You can do like this to call the python file from the C program:
char command[50] = "python full_path_name\\file_name.py";
system(command);
This piece of code worked for me...
I didn't use # include < python2.7/Python.h>
You can write the results from the python file to any text file and then use the results stored in the text file to do whatever you want to do...
You can also have a look at this post for further help:
Calling python script from C++ and using its output
Related Topics
Why Must the Copy Assignment Operator Return a Reference/Const Reference
What's the Difference Between Std::Move and Std::Forward
Why Does C++ Allow Us to Surround the Variable Name in Parentheses When Declaring a Variable
What's "Wrong" With C++ Wchar_T and Wstrings? What Are Some Alternatives to Wide Characters
"Invalid Use of Incomplete Type" Error With Partial Template Specialization
Remove Comments from C/C++ Code
Undefined Symbol _Gxx_Personality_V0 on Link
How to Use the Qt'S Pimpl Idiom
Int A[] = {1,2,}; Why Is a Trailing Comma in an Initializer-List Allowed
How to Get Memory Usage At Runtime Using C++
How to Efficiently Select a Standard Library Container in C++11