469,929 Members | 1,811 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,929 developers. It's quick & easy.

Problem with C-API

Hi

I spent the whole of yesterday trying the get the following C code to
execute

PyRun_String("def title();", Py_file_input, dict, dict);
PyRun_String("\treturn 'Foo Bar'", Py_file_input, dict, dict);
PyRun_String("x = title()", Py_file_input, dict, dict);
PyObject * result = PyRun_String("print x", Py_file_input, dict, dict);
printf( "The result is %s\n", PyObject_AsString( result );

Each line throws an error.

Could somebody tell what is wrong with the above code.

Here below is the output from my test app

Starting Test ......

The file "testtitle" is open for reading

The variable codeStrings contains

Line 0 def title()
Line 1 return "Foo Bar"

The variable scriptText contains

def title()
return "Foo Bar"

The variable tempList contains

Line 0 testtitle
Line 1 title

Module Name is testtitle

Function Name is title

The variable functionCode contains

def title()
return "Foo Bar"

Python initialized successfully

Module object successfully created

Dict object successfully created

Failed to create a Result object.

The title of the this task is <nil>

--
Best Regards
John
Mar 17 '06 #1
6 3955
John Dean wrote:
Hi

I spent the whole of yesterday trying the get the following C code to
execute

PyRun_String("def title();", Py_file_input, dict, dict); ^^^^^^^^^^^

Try using a colon here....
PyRun_String("\treturn 'Foo Bar'", Py_file_input, dict, dict);
PyRun_String("x = title()", Py_file_input, dict, dict);
PyObject * result = PyRun_String("print x", Py_file_input, dict, dict);
printf( "The result is %s\n", PyObject_AsString( result );

Overall it seems to me that ther must be a better way to do such a thing -
even in C. AFAIK it supports multiline-stringliterals. Why don't you do
something like this:

script = "\
def foo():\n\
return 'FooBar'\n\
x = title()\n\
print x\n"

And then read that script line by line, feeding it to the parser. Or maybe
the parser even groks that string at once - don't know that.
Diez
Mar 17 '06 #2
John Dean wrote:
PyRun_String("def title();", Py_file_input, dict, dict);
PyRun_String("\treturn 'Foo Bar'", Py_file_input, dict, dict);
PyRun_String("x = title()", Py_file_input, dict, dict);
PyObject * result = PyRun_String("print x", Py_file_input, dict, dict);
printf( "The result is %s\n", PyObject_AsString( result );

Each line throws an error.


Please don't paraphrase your code when asking questions such as this. The
code above doesn't even compile (unmatched parentheses) so any response
must be a guess as to which parts were wrong in your original code and
which errors you introduced just for the posting.

Each call to PyRun_String is independant. You seem to think you can call
the function with part of your source code and then continue with more of
the source in another call. You cannot.

Try concatenating the lines together to at least make complete statements.
Also make sure to handle the result from every call to PyRun_String: check
it for null, if it is null you should format and print the error message.

The following is your code rewritten as a working program. When you run it,
it will tell you about the syntax error in your Python code. Fix that and
you will see your program output.

#include <python.h>

void run() {
PyObject *dict = PyDict_New();
PyObject *result;
if (dict==NULL) {
PyErr_Print();
return;
}

result = PyRun_String("def title();\n\treturn 'Foo Bar'\n",
Py_file_input, dict, dict);
if (result==NULL) {
PyErr_Print();
return;
} else {
Py_DECREF(result);
}

result = PyRun_String("x = title()", Py_file_input, dict, dict);
if (result==NULL) {
PyErr_Print();
return;
} else {
Py_DECREF(result);
}

result = PyRun_String("print x", Py_file_input, dict, dict);
if (result==NULL) {
PyErr_Print();
return;
} else {
PyObject *rString = PyObject_Str(result);
if (rString==NULL) {
Py_DECREF(result);
PyErr_Print();
return;
}

printf( "The result is %s\n", PyString_AsString(rString));
Py_DECREF(rString);
Py_DECREF(result);
}
}

int main(int argc, char **argv) {
Py_Initialize();
run();
}

Mar 17 '06 #3
Hi Duncan

Your version of the app works apart from this part

.....
.....

else {
PyObject *rString = PyObject_Str(result);
if (rString==NULL) {
Py_DECREF(result);
PyErr_Print();
return;
}

printf( "The result is %s\n", PyString_AsString(rString));
Py_DECREF(rString);
Py_DECREF(result);
}
}

The result of the printf state is: "The result is None"
result = PyRun_String("print x", Py_file_input, dict, dict);

The above line of code displays the value returned from the title()
function. My problem is I need to be able to cature the return value because
in the real application it will be displayed in a Process Log Widget. Also
the real scripts will be much longer.

I have not had a problem writing Python extensions, but when it comes to
embedded Python I just see how to get my code to work.

Any further help would be greatly appreciated

--
Best Regards
John
Mar 17 '06 #4
Hi

Duncan's example worked to a point. The line PyRun_String( "print x",
Py_file_input, dict, dict); print out the contents of x, but I don't want to
print x out. I want to be able to grab whateven the variable x contains so
that I can pass it on for further processing by the C++ application.

BTW this is only a test case. The real scripts are much bigger. I must say
the documentation is not of much help and there are no books or articles
covering embedding Python in any detail. What there is is very much out of
date.

--
Best Regards
John
Mar 17 '06 #5
John Dean wrote:
Duncan's example worked to a point. The line PyRun_String( "print x",
Py_file_input, dict, dict); print out the contents of x, but I don't want to
print x out. I want to be able to grab whateven the variable x contains so
that I can pass it on for further processing by the C++ application.
a better approach is to combine embedding and extending, and let the em-
bedded code use your extension to talk to your program.

if you want your program to access x, let the embedded script do

import myapp
myapp.write(x)

since you know how to extend Python, implementing write should be trivial.

if you insist on picking out variables from the embedded script, you can use
the same approach as when you want to pull out variables from code you've
exec'ed: run the code in a namespace dictionary, and extract the data from
the dictionary after you've run the code. i.e.

g = {}
exec code in g
x = g["x"]

becomes

PyObject *g, *x;
g = PyDict_New();
PyDict_SetItemString(g, "__builtins__", PyEval_GetBuiltins());
PyRun_String(mycode, Py_file_input, g, NULL);
x = PyDict_GetItemString(g, "x");
Py_DECREF(g);

(the SetItemString call is probably not needed in all cases)
BTW this is only a test case. The real scripts are much bigger. I must say
the documentation is not of much help and there are no books or articles
covering embedding Python in any detail. What there is is very much out of
date.


well, I'm getting a bit tired of all this "if it's not published within the last
few weeks, it's out of date" nonsense that people keep using as an excuse
for procrastination. The Python C API is very stable, and the embedding
and extending basics haven't changed a bit in a decade.

and "no books" is also wrong; ORA's "Programming Python" spends some
40 pages on embedding only (including examples on how to extract stuff
from module namespaces). I'm pretty sure it's not the only one.

</F>

Mar 18 '06 #6
John Dean wrote:
Hi Duncan

Your version of the app works apart from this part

....
....

else {
PyObject *rString = PyObject_Str(result);
if (rString==NULL) {
Py_DECREF(result);
PyErr_Print();
return;
}

printf( "The result is %s\n", PyString_AsString(rString));
Py_DECREF(rString);
Py_DECREF(result);
}
}

The result of the printf state is: "The result is None"
Yes, what did you expect it to be? The result from executing the Python
code was the value None.


result = PyRun_String("print x", Py_file_input, dict, dict);

The above line of code displays the value returned from the title()
function. My problem is I need to be able to cature the return value
because in the real application it will be displayed in a Process Log
Widget. Also the real scripts will be much longer.

I have not had a problem writing Python extensions, but when it comes
to embedded Python I just see how to get my code to work.

Any further help would be greatly appreciated

If you want the value of x, then pick it out of the dictionary:

{
PyObject *x = PyDict_GetItemString(dict, "x");
PyObject *rString = PyObject_Str(x);
printf( "x is %s\n", PyString_AsString(rString));
Py_DECREF(rString);
Py_DECREF(x);
}
Py_DECREF(dict); // I forgot this one in my original code.

If you want to embed Python though you really should look at Pyrex. Using
Pyrex you can all but forget about the Python api, write a Pyrex function
which is callable directly from C: it calls the Python code and returns the
C values you want as a result. Also it will handle all the error checking
and reference counting automatically.
Mar 18 '06 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Kostatus | last post: by
117 posts views Thread by Peter Olcott | last post: by
18 posts views Thread by Ian Stanley | last post: by
28 posts views Thread by Jon Davis | last post: by
6 posts views Thread by Ammar | last post: by
2 posts views Thread by Mike Collins | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.