FAQ
Hi,

Please CC me as Im not subscribed.

Is it possible to pass variables from C into an
embedded Python interpreter and have them available
from inside a script that gets executed via something
similar to PyRun_SimpleFile()? For example, I want to
be able to accept a socket connection in C, pass it
into a python script, and have it available to the
script when it executes.

Eg. (in C)
Py_Initialize();
...
mysock = accept(connfd, (struct sockaddr *)&addr,
&size);
Py_PassVarToPython( "sock", (PyObject *)&mysock );
PyRun_SimpleFile( scriptfd, "test.py" );
...
Py_Finalize();

Then, from the test.py script be able to access the
socket via os.read(), os.write(), etc:

buff = os.read( sock, 1024 );
...
os.write( sock, "hello world" );

Im sure that the call to python is not acctually going
to be PyRun_SimpleFile(). That is just to illustrate
the functionality I want, i.e., handle some basics is
C, then turn the data over to the embedded interpreter
that executes an external script.

Thanks,

db

__________________________________
Do you Yahoo!?
The New Yahoo! Search - Faster. Easier. Bingo.
http://search.yahoo.com

Search Discussions

  • Syver Enstad at May 7, 2003 at 6:43 am

    db <dbunix at yahoo.com> writes:

    Hi,

    Please CC me as Im not subscribed.

    Is it possible to pass variables from C into an
    embedded Python interpreter and have them available
    from inside a script that gets executed via something
    similar to PyRun_SimpleFile()?
    Yes, but you can only pass Python objects into python code. In other
    words, you have to create Python objects in your C code and then pass
    them to python. The scenario you present is a quite typical one, you
    will typically have to write a Python C extension type that enables python
    to use your C object.

    Like this:
    // the module you want to pass your C extension type to
    PyObject* module = PyImport_ImportModule("MyModule");
    PyObject* entryFunction = PyObject_GetAttrString(module, "MyFunc");
    // arg1 and arg2 would be data that you want to expose to Python in
    // some fashion
    PyObject* myextensionType = YouDefineThisFunction(arg1, arg2);
    PyObject_CallFunction(entryFunction, "O", myExtensionType);

    // NB, any error checking or reference counting is left out to make it
    // simpler.

    For example, I want to
    be able to accept a socket connection in C, pass it
    into a python script, and have it available to the
    script when it executes.
    For the socket example, there already exists a socket c module so you
    should probably use that instead of writing your own wrapper.

    --

    Vennlig hilsen

    Syver Enstad
  • Db at May 7, 2003 at 8:16 am

    Syver Enstad wrote:

    Yes, but you can only pass Python objects into python
    code. In other words, you have to create Python objects
    in your C code and then pass them to python. The
    scenario you present is a quite typical one, you will
    typically have to write a Python C extension type that
    enables python to use your C object.
    Since a socket is just a int in C, is it possible that
    I could just use something like:
    PyObject *mysock = Py_BuildVal( "i", sockfd );
    rather then creating my own type? I'll probably be
    able to answer this myself when Im able to get back to
    my code. :)
    Like this:
    // the module you want to pass your C extension type to
    PyObject* module =
    PyImport_ImportModule("MyModule");
    PyObject* entryFunction =
    PyObject_GetAttrString(module, "MyFunc");
    // arg1 and arg2 would be data that you want to
    expose to Python in
    // some fashion
    PyObject* myextensionType =
    YouDefineThisFunction(arg1, arg2);
    PyObject_CallFunction(entryFunction, "O",
    myExtensionType);

    If what I wrote above is true, this could be:
    PyObject_CallFunction( entryFunction, "i", sockfd );
    For the socket example, there already exists a
    socket c module so you
    should probably use that instead of writing your own
    wrapper.

    I saw this too, but I don't think I can use it in the
    manner I propose. Python "sockets" are objects based
    on a struct called PySocketSockObject defined in
    Modules/socketmodule.c. They store other bits of
    information other then the SOCKET_T sock_fd field
    which is the low level part that I need. As the struct
    is defined directly in the module and not in Python.h
    header file, I don't think I have access to it even
    from a C extension. Please correct me if Im wrong or
    there is a way to convert a open C socket (i.e. an
    int) into a Python socket object.

    Thanks for your help!

    db

    __________________________________
    Do you Yahoo!?
    The New Yahoo! Search - Faster. Easier. Bingo.
    http://search.yahoo.com
  • Syver Enstad at May 7, 2003 at 7:48 pm

    db <dbunix at yahoo.com> writes:

    Since a socket is just a int in C, is it possible that
    I could just use something like:
    PyObject *mysock = Py_BuildVal( "i", sockfd );
    rather then creating my own type? I'll probably be
    able to answer this myself when Im able to get back to
    my code. :)
    Yes, you could do that, but how are you going to use the int from
    python? I don't know the socket library by heart, so I popped up the
    documentation and I see that socket.fromfd might help. It takes an
    integer and creates a python socket object from it. So that way you
    could create your socket on the C side and pass it into python as an
    int and then use it from python by doing socket.fromfd

    If what I wrote above is true, this could be:
    PyObject_CallFunction( entryFunction, "i", sockfd );
    Yes, using CallFunction you don't even have to create a Python integer
    object, sockfd could be the raw C int.
    Please correct me if Im wrong or
    there is a way to convert a open C socket (i.e. an
    int) into a Python socket object.
    See above regarding socket.fromfd. You could call this function from
    the C code too, by using the Python C api.

    Some thing like this (not tested).
    PyObject* socketMod = PyImport_ImportModule("socket");
    PyObject* fromFdFunc = PyObject_GetAttrString(module, "fromfd");
    PyObject_CallFunction(fromFdFunc, "iBlaBla", yourSocketAsCint,
    otherArgs1, and2, andSoOn);

    It's up to you if you want to do the conversion in python code or
    convert it before passing it into your python function.

    --

    Vennlig hilsen

    Syver Enstad
  • Db at May 8, 2003 at 3:16 am

    Syver Enstad wrote:

    Yes, you could do that, but how are you going to use
    the int from
    python?
    Using os.read() and os.write() like I mentioned in my
    first mail. posix_write(fd,str) quite neatly parses
    its first argument into an int, then passes it
    directly to the write(2) system call, just like I
    need.

    I did get this to work! :) It didn't for quite a while
    until I realized that I needed to "import os" as the
    first line of my python script in order to get
    os.write() . I felt like a complete noob :P

    Here is the setup (based on your help from yesterday)
    sans error checking:
    In C:
    int sockfd;
    PyObject *module, *function, *ret;
    sockfd = accept( blah, blah, blah );

    module = PyImport_ImportModule( "mymod" );
    function = PyObject_GetAttrString( module, "myfunc" );
    ret = PyObject_CallFunction( function, "i", sockfd );

    In mymod.py:
    import os // the key ;)
    def myfunc( out )
    os.write( out, "Hello from Python on socket\n" )

    So, now I have python talking over a pre-opened socket
    from C, yay! Ok, now that I've got all that working, I
    wish to break it again, so I have a couple more
    questions.

    First is error checking/exception handling. The
    embedding manual discusses how to create/set
    exceptions for handling in python, but not how to get
    that info from C. Right now I have something lame
    like:
    ret = PyObject_CallFunction( function, "i", sockfd );
    if( ret == NULL )
    {
    print( "Call to myfunc failed\n" );
    exit( 1 );
    }

    This is enough to tell me when stuff breaks, but not
    Python's reason for why. I see there are variables
    like sys.exc_type, sys.exc_value, and
    sys.exc_traceback that must have C equivalents. Are
    there sane Python C API calls that allow me to get at
    these variables? Im guessing something about importing
    sys and extracting more variables?
    PyObject *sysmod = PyImport_ImportModule("sys");
    PyObject *trace = PyObject_GetAttrString( sysmod,
    "exc_traceback" );
    Or is it part of the PyErr_* family?

    Second, is it possible to import modules from C and
    have them appear already imported in the script? For
    example, is there a way I could load the "os" module
    and then remove the first line of my script and still
    have os.write() work? I tried adding a call to
    PyImport_ImportModule( "os" ) before I call
    PyObject_CallFunction() but it didn't seem to work.

    Finally, is it possible to compile the python script
    and save the result for execution later with different
    sets of inputs?
    PyObject *code = Py_Compile( "mymod" );
    PyObject *val1 = Py_BuildValue( "i", someint );
    PyObject *result1 = Py_Execute( code, val1 );
    PyObject *val2 = Py_BuildValue( "i", anotherint );
    PyObject *result2 = Py_Execute( code, val2 );

    I've been through the C API reference manual and
    didn't see anything that fit, but looking through the
    source makes me think it might be possible. I know
    this is getting pretty advanced, and I really
    appreciate the help you've given me already.

    Thanks again,

    db

    __________________________________
    Do you Yahoo!?
    The New Yahoo! Search - Faster. Easier. Bingo.
    http://search.yahoo.com

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedMay 6, '03 at 9:31p
activeMay 8, '03 at 3:16a
posts5
users2
websitepython.org

2 users in discussion

Db: 3 posts Syver Enstad: 2 posts

People

Translate

site design / logo © 2022 Grokbase