471,594 Members | 1,560 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,594 software developers and data experts.

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

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
0 2079

Post your reply

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

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.