Hello,
I'm writing a simple calculator in C. The main problem is I need to parse string to evaluate for example 1+2*(3-1)/2.5.
However writing such parses is a very hard task.

This is a trivial thing Python using this code:

s = raw_input('Please enter expression:')
try:
  x = eval(s)
except NameError:
  print 'Unknown elements in the expression!'
except ZeroDivisionError:
  print 'Division with zero attempted!'
except:
  print 'Some other kind of error!'
else:
  print 'Expression is evaluated correctly'

I saw that Python has C API so I assume that Python functions can be called from C.

Is it possible to use Python function eval() to evaluate user string in C program? In other words is it possible to make wrapper to this Python code and evaluate expression in C?
I tried to find answer in Python manual but I'm a complete jackass beginer.

For example I have Test.c

#include <stdio.h>

char buff[BUFSIZ];

int main(void)
{
	char * p;
	double res;/* to store result of expression evaluation*/

	printf ("Please enter expression: ");
	fgets(buff, sizeof buff, stdin);
	if (p = strrchr(buff,'\n'))
	{
		*p = '\0';
	}

	/* now wrapper to python function eval()-....? */
}

and from that c file I'd like to call eval and if success to store result to variable res.

I'm using MSCV++ .NET with Win XP and I assume I'll need to use some kind of Python libraray...
There is explanation in Pythion doc, but there is no complete testing source file and my english is not very good to understand all the described steps.
Is this possible at all?

Please, can you help me?

Thanks in advance!

Recommended Answers

All 10 Replies

well I manage to figure it out myself. I'm using Bloodshed Dev-cpp
Here's the code:

#include "python.h"
#include <stdio.h>

int main(int argc, char* argv[])
{
	double answer = 0;
	PyObject *modname, *mod, *mdict, *func, *stringarg, *args, *rslt;
         
	Py_Initialize();
    modname = PyString_FromString("Test");
    mod = PyImport_Import(modname);
	if (mod) 
	{
		mdict = PyModule_GetDict(mod);
		func = PyDict_GetItemString(mdict, "doit"); /* borrowed reference */
		if (func) 
		{
			if (PyCallable_Check(func)) 
			{
				stringarg = PyString_FromString("5");/*pay attention here*/
				args = PyTuple_New(1);
				PyTuple_SetItem(args, 0, stringarg);
				rslt = PyObject_CallObject(func, args);
				if (rslt) 
				{
					answer = PyFloat_AsDouble(rslt);
					Py_XDECREF(rslt);
				}
              Py_XDECREF(stringarg);
              Py_XDECREF(args);
			}
		}
         
		Py_XDECREF(mod);
	}
         
	Py_XDECREF(modname);
         
	Py_Finalize();
		 
	printf("%g",answer);
         
	return 0;
}

I need to add include and lib directories to the project in order to everything works fine. Also Test.py is copied in Dev-cpp source code's folder.
Test file contains the following code

def doit(x1):
    try:
        x2 = eval(x1)
    except:
        print 'Error!'
        return 0

    else:
        return x2

However there is an error. Look at the line stringarg = PyString_FromString("5"); If I put this:
stringarg = PyString_FromString("5+2"); or even this stringarg = PyString_FromString("5.0");
Program crashes at line Py_Finalize(). Program tries to read some memory location and suffer run time exception.
Only suggestion is to try to send it to Microsoft.
Why is this happening?
Everything (seems to) works fine I comment line Py_Finalize(), but I know that this is not a real solution.

Does anybode have a clue what is happening?

Thanks

A little twist here, the Python24.dll contains all the PyEval routines and they are most likely written in C. So I wonder, if you couldn't access them directly from the dll in your C/C++ program.

A little twist here, the Python24.dll contains all the PyEval routines and they are most likely written in C. So I wonder, if you couldn't access them directly from the dll in your C/C++ program.

I really don't know what you mean. Are you asking me if I had problems with linking library (in MSVC++ I had) python24.lib or what?

And also, can you help me to figure out why I'm getting that nasty send to Microsoft window and why my program read memory which is not supposed to?

Thank you

Well, I manage to embed Python eval function in C code.
If anyone is interested let me know to post solution.
Cheers

- Micko

Super job Micko! Why don't you post it right here, or better even in the Python snippetts.

If you have Dev-C++, embedding Python is quite easy with the free Python Development Pak. Look at this C++ code snippet for more information:
http://www.daniweb.com/code/snippet387.html

For the masochists, this might be one way to create an executable Python file. Come to think of it, you could let a Python program do the nasty detailed work!

Thanks I have forgotten to paste my solution
Here it is:

C file:

#ifdef _DEBUG
  #undef _DEBUG
  #include "python.h"
  #define _DEBUG
#else
  #include "python.h"
#endif

#include "python.h"
#include <stdio.h>

int main (int argc, char* argv[])
{

	double answer = 0.0;
	char buff [BUFSIZ];
	char * p;
	int test = 0;

	PyObject *modname, *mod, *mdict, *func, *stringarg, *args, *rslt;

	fputs ("Enter expression: ",stdout);
	fgets (buff, sizeof buff, stdin);
	
	if (p = strrchr (buff, '\n'))
	{
		*p = '\0';
	}

	Py_Initialize();
    modname = PyString_FromString ("Test");
    if (modname == NULL)
    {
    	Py_Exit(0);
    	return 0;
   	}
    mod = PyImport_Import (modname);
    if (mod) 
	{
		mdict = PyModule_GetDict (mod);
		func = PyDict_GetItemString (mdict, "izracunaj");
		if (func) 
		{
			if (PyCallable_Check (func)) 
			{
				stringarg = PyString_FromString (buff);
				args = PyTuple_New (1);
				PyTuple_SetItem (args, 0, stringarg);
				rslt = PyObject_CallObject (func, args);
				if (rslt)
        		{      
					if (PyFloat_Check(rslt)) 
					{
						answer = PyFloat_AsDouble(rslt);
						test = 1;
					} 
					else if (PyInt_Check(rslt))
					{
						answer = PyInt_AsLong(rslt);
						test = 1;
					}
					else 
					{
						printf ("Nije korektan izraz!\n");
					}
					 Py_XDECREF(rslt);
				} 
           
				Py_XDECREF(args); 
			}
			
		}
		else
		{
			printf("Kivla");
		}
			Py_XDECREF(mod);
	}  
	else
	{
		printf("Python module mora biti u istom direkoriju!\n");
		PyErr_Print();
	}
	
	Py_XDECREF(modname);

	if (test)
	{
		printf("Izracunat je %g\n",answer);
	}
	
    return 0;
}

Python file:

from math import *
from __future__ import division
def izracunaj():
	x = raw_input ('Enter expression:')
	try:
		y = eval(x)
	except NameError:
		print 'Wrong expression'
	except:
		print 'error in evalution'

	else:
		print  '%g' % y

I used MSVC++ .net v2002
i set project path to include folder in Python directory and also includede path for libraries and that was it. I placed Python file in the same project folder in MSVC++

Hi can you help me im new in python; i tried to call python functions inside c++ and i copied your sample source code and put it in my created function. I comment out the Py_Initialize() and Py_Finalize() because they are called in different part of the program.

I put a break point in the function but the problem is when the game reads the line: func = PyDict_GetItemString(mdict, "PnlPackSel"); it returns NULL.

Any help will be appreciated

C++ Source code:

int  GC_PythonCalls()
{

    double answer = 0;
    PyObject *modname, *mod, *mdict, *func, *stringarg, *args, *rslt;

//  Py_Initialize();
    modname = PyString_FromString("Menu");
    mod = PyImport_Import(modname);
    if (mod) 
    {

        mdict = PyModule_GetDict(mod);
        func = PyDict_GetItemString(mdict, "PnlPackSel"); /* borrowed reference */
        if (func) 
        {
            if (PyCallable_Check(func)) 
            {

                rslt = PyObject_CallObject(func, NULL);
                if (rslt) 
                {
                    //answer = PyFloat_AsDouble(rslt);
                    Py_XDECREF(rslt);
                    OutputDebugString("PY CALL SUCCESS \n");
                }
              Py_XDECREF(stringarg);
              Py_XDECREF(args);
            }
        }

        Py_XDECREF(mod);
    }

    Py_XDECREF(modname);

    //Py_Finalize();



    return 0;
}

Python Code

def PnlPackSel(self):
    App.CtrlMouseSet(100,100) 
    Pnl = self.PCtrlTopGet();
    #bring
    self.PCtrlAdd(
        self.__class__.AddLvl,
        (self, Pnl.ulPackId, False),
        True,
        );

Thanks in advance

I forgot to mention PnlPackSel function is under CButtonInfo Python Class and CButtonInfo is under CMenuMod class.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.