+ Reply to Thread
Results 1 to 9 of 9

Thread: Embending Python into C/C++ : how to send a C structure to Python ?

Hybrid View

  1. #1
    Senior Member
    Join Date
    Aug 2004
    Location
    France
    Posts
    292

    Default Embending Python into C/C++ : how to send a C structure to Python ?

    Hello,

    I just began to dig into Python, and although the language itself seems to be nice, and the bases of embedding into C/C++ easy enough (although not too easy), I have a super hard time to find a tutorial, a doc, or anything to let me know how to do this :
    I want to send a pointer to a structure from my C code to a Python function, and then modify the C structure from within Python.

    The idea is that I have my Player State + my Game State, and I want to send 2 pointers, 1 for each state to a Python function that will modify the Player State according to some scripted game logic...

    All I could find about this matter was a few comments about people telling they spent days to try to achieve something like this, and finally they went to use LUA...

    It seems SWIG could do the job, but in its doc, there's nothing about passing C structure as argument to Python functions; they only describe direct use of these structures from within Python.

    I had a look at Boost.Python, which is mainly for extending Python through C++, with almost nothing to embed Python with C++...

    I very wonder why something so basic & useful is never described in all docs & tutorials I came through till now...
    So if anyone could give me an hand on this, I'd be very thankful...

    PS: my favorites links so far to startup with Python :
    Learn Python in 10 minutes : http://www.poromenos.org/tutorials/python? (actually, it's more like a little hour )
    Embedding Python in Your C Programs : http://www.linuxjournal.com/article/8497 (quite good tuto to know the basis to embed Python within C/C++)
    Python Extension writing : http://www.ragestorm.net/tutorials/25/pyext.html (gives the basis to add new type to Python, it looks like the way to go to add C structures as new types)

  2. #2
    Senior Member
    Join Date
    Aug 2004
    Location
    France
    Posts
    292

    Default

    Just while I were looking for a more "Python place" to post my previous query, I found out the comp.lang.python newsgroup :
    http://groups.google.com/group/comp....ture+argument#
    Once again, another programmer who was stuck on the same problem than me, who "just" needed 1 week to solve it...
    It looks like I'm going to walk in his steps, and hopefully by following his solution, I'd need less time than him to produce something actually useful...

  3. #3

    Default

    using boost::python, can't you just put the pointer into a python var?
    Something like:

    struct GameState {};
    GameState gameState;
    boost::python::globals["gameState"] = &gameState;

    You need to provide the python mapping for GameState of course.
    That's at least how it works with luabind and what I gathered from a quick glance over the boost python docs.

    hth,
    Tony

  4. #4
    Senior Member
    Join Date
    Aug 2004
    Location
    France
    Posts
    292

    Default

    This :
    "boost:: python::globals["gameState"] = &gameState;"
    is not C++ ...
    Maybe it's C# ..?

    Anyway, I had more than a glance a Boost.Python, and I didn't see anything like this (I might have looked in the wrong place, though... :S )

    And yup, 50% of the problem is to have my structure recognized from within Python, which seems to be done by "object = MyObjectPtr(o)" when using Swig... Going to check that today, fingers crossed...

    PS: yup, it ain't easy to code with my fingers crossed

  5. #5
    Junior Member
    Join Date
    Feb 2008
    Location
    Karlsruhe, Germany
    Posts
    22

    Default

    Quote Originally Posted by ManuTOO View Post
    This :
    "boost:: python::globals["gameState"] = &gameState;"
    is not C++ ...
    Maybe it's C# ..?
    This is actually perfectly running code from Tony's and my C++ sources...

    After a quick look into boost:: python docs one can come up with a solution like this (you would pack this into modules and stuff for production code):

    Code:
    #include <iostream>
    #include <string>
    #include <boost/python.hpp>
    
    using namespace boost::python;
    
    struct World
    {
      std::string msg;
      void greet()
      {
        std::cout << msg << std::endl;
      }
    };
    
    int main (int argc, char * const argv[])
    {
      try
      {
        // Initialize context
        Py_Initialize();
    
        // Retrieve the main module.
        object main_module((handle<>(borrowed(PyImport_AddModule("__main__")))));
    
        // Retrieve the main module's namespace
        object main_namespace(main_module.attr("__dict__"));
        
        // Expose World class
        main_namespace["World"] = class_<World>("World")
                                    .def_readwrite("msg", &World::msg)
                                    .def("greet", &World::greet);
    
        // Expose World instance
        World world;
        main_namespace["world"] = ptr(&world);
    
        // Run script
        handle<> ignored(( PyRun_String("world.msg = 'Hello World!' \n"
                                        "world.greet()              \n",
                                        Py_file_input,
                                        main_namespace.ptr(),
                                        main_namespace.ptr() ) ));
        
        // Finalize context
        Py_Finalize();
      }
      catch( error_already_set )
      {
        PyErr_Print();
      }
      
      return 0;
    }
    Edit: I just saw that you want to pass the structure into python. For that you could do the following (replace from "// Expose World instance"):
    Code:
        // Define python function
        handle<> ignored(( PyRun_String("def use_world(world):         \n"
                                        "   world.msg = 'Hello World!' \n"
                                        "   world.greet()              \n",
                                        Py_file_input,
                                        main_namespace.ptr(),
                                        main_namespace.ptr() ) ));
        
        // Create World instance
        World world;
    
        // Get python function...
        object use_world = main_namespace["use_world"];
        
        // ...and call it
        use_world(world);
    cheers,
    Timo
    Last edited by jomanto; 08-13-2008 at 01:04 AM.

  6. #6
    Senior Member
    Join Date
    Aug 2004
    Location
    France
    Posts
    292

    Default

    Hello jomanto, your "World" is not exactly a structure, it's a class with everything in public, and if I recall well, it's an ease of the language to let structures behave like classes.
    Me, I meant a struct, in the 1st C meaning, ie: a gathering a variables, and possibly other structures.

    So I don't need to expose functions. I just want to expose the variables (which can be structures as well), and I don't want to do it manually (I already have plenty and if I add more, I don't want to do maintenance).

    But thanks for ur example, as it'd be a good start, and better than nothing if I can't succeed with Swig...


    PS: my bad for the "boost:: python::globals["gameState"] ", of course it can be done in C++ if "globals" is an object from a class with an overloaded [] operator.

+ Reply to Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts