By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
435,543 Members | 2,169 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,543 IT Pros & Developers. It's quick & easy.

How to create Python function in c++ & call it multiple times

P: 4
I am new to Python. I would like to use Python for the specialized purpose of dynamic expressions parsing & evaluation in my C++ application.
I would like to encapsulate the expressions to be evaluated in Python function & compile that function at runtime, somewhat as below.
Expression to eval put in Python function
def isSizeSmall(size,vol,ADV,prod):
if ( (size < 1000) & (vol < (0.001 * ADV)) & (prod=="Stock")): print "OK"; return 10
else: print "NOK"; return 11

Then, I want to evaluate the PyObject returned by Py_CompileString multiple times in my program using the user input as the variables to the above function.
This I tried using two different approaches - 1) PyEval_evalCode, & 2) PyObject_CallObject.

1) When using PyEval_evalCode: The function call to PyEval_evalCode was ok, but it did not return any output.
2) Whereas, when I used this object with PyObject_CallObject, it failed with error as given below.

Any help will be great. Many thanks in advance for your help.
Warm Regards,
Ganesh

//***********************************************//
Output of my test program:
Expression to eval =
"def isSizeSmall(size,vol,ADV,prod):
if ( (size < 1000) & (vol < (0.001 * ADV)) & (prod=="Stock")): print "OK"; return 10
else: print "NOK"; return 11"


str compiled fine with stdin & Py_file_input, calling PyEval_EvalCode
None ok [0] size [-1]

str compiled fine with stdin & Py_file_input, calling PyFunction_New & then PyObject_CallObject
Getting PyFunction_New
Calling PyObject_CallObject
func is callable
TypeError: ?() takes no arguments (4 given)

My test program having both above approaches is as below:
Expand|Select|Wrap|Line Numbers
  1. main(int argc, char **argv)
  2. {
  3.    /* Pass argv[0] to the Python interpreter */
  4.    Py_SetProgramName(argv[0]);
  5.    /* Initialize the Python interpreter.  Required. */
  6.    Py_Initialize();
  7.    PyRun_SimpleString("import sys\n");
  8.  
  9.    char szExpr[2048];
  10.    memset(szExpr,'\0',sizeof(szExpr));
  11.    sprintf(szExpr,"def isSizeSmall(size,vol,ADV,prod):\n  if ( (size < 1000) & (vol < (0.001 * ADV)) & (prod==\"Stock\")): print \"OK\"; return 10\n  else: print \"NOK\"; return 11\n\n\n");
  12.  
  13.    printf("Expression to eval = \n[%s]\n",szExpr);
  14.  
  15.    OrderValues ordval;
  16.    ordval.size = 100;
  17.    ordval.ADV  = 100000;
  18.    ordval.vol  = 1000;
  19.    memset(ordval.prod,'\0',sizeof(ordval.prod));
  20.    sprintf(ordval.prod,"Stock");
  21.  
  22.  
  23.    PyObject *glb, *loc;
  24.  
  25.    glb = PyDict_New();
  26.    PyDict_SetItemString(glb, "__builtins__", PyEval_GetBuiltins());
  27.  
  28.    loc = PyDict_New();
  29.  
  30.    PyObject* tuple = PyTuple_New(4);
  31.    PyObject* val = 0;
  32.  
  33.    val = PyInt_FromLong(ordval.size);
  34.    PyTuple_SetItem(tuple,0,val);
  35.    PyDict_SetItemString(loc,"size",val);
  36.  
  37.    val = PyInt_FromLong(ordval.vol);
  38.    PyTuple_SetItem(tuple,1,val);
  39.    PyDict_SetItemString(loc,"vol",val);
  40.  
  41.    val = PyInt_FromLong(ordval.ADV);
  42.    PyTuple_SetItem(tuple,2,val);
  43.    PyDict_SetItemString(loc,"ADV",val);
  44.  
  45.    val = PyString_FromString(ordval.prod);
  46.    PyTuple_SetItem(tuple,3,val);
  47.    PyDict_SetItemString(loc,"prod",val);
  48.  
  49.  
  50. /*** with string & Py_file_input ***/
  51.    PyObject* result = NULL;
  52.    result = Py_CompileString(szExpr,"<string>", Py_file_input);
  53.    if(result!=NULL && !PyErr_Occurred()){
  54.      printf("str compiled fine with stdin & Py_file_input, calling PyEval_EvalCode\n");
  55.  
  56.      PyCodeObject *pyCo = (PyCodeObject *)result;
  57.      PyObject* evalret = NULL;
  58.      evalret = PyEval_EvalCode(pyCo,glb,loc);
  59.      if(!evalret || PyErr_Occurred())
  60.        PyErr_Print();
  61.      else
  62.         printf("ok [%d] size [%d]\n",PyObject_Print(evalret,stdout,0),PyObject_Size(evalret));
  63.  
  64.      // Try to get function obj of this...
  65.      printf("Getting PyFunction_New\n");
  66.      PyObject* func = PyFunction_New(result,glb);
  67.      if(!func || PyErr_Occurred()){
  68.        printf("Failed to get Function..\n");
  69.        PyErr_Print();
  70.      } else {
  71.          printf("Calling PyObject_CallObject\n");
  72.          if(PyCallable_Check(func))
  73.            printf("func is callable\n");
  74.          PyObject* ret = PyObject_CallObject(func, tuple);
  75.          //PyObject* ret = PyObject_CallObject(func, NULL);
  76.          if(!ret || PyErr_Occurred())
  77.            PyErr_Print();
  78.          else
  79.            printf("PyObject_CallObject evaluated..\n");
  80.      }
  81.    } else {
  82.          printf("Py_CompileString-1 returned NULL\n");
  83.          PyErr_Print();
  84.    }
  85.    exit(100);
  86. }
Nov 21 '07 #1
Share this question for a faster answer!
Share on Google+

Post your reply

Sign in to post your reply or Sign up for a free account.