[C++-sig] Executing python code from C++

2010-02-07 Thread Murray Cumming
In Glom, to execute arbitrary Python code, I use PyRun_String() to parse
the Python code, PyDict_GetItemString() and PyObject_Call() to get a
callable object for that code, and then PyObject_CallObject() to
actually execute the code and get a return value. This was the result of
experimentation and code archeology:
http://git.gnome.org/browse/glom/tree/glom/python_embed/glom_python.cc?h=glom-1-12#n269

Is there anything in boost::python that wraps this, so I can make the
code nicer?

-- 
[email protected]
www.murrayc.com
www.openismus.com

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


[C++-sig] Checking for or null PyObject* or PyNone

2010-02-07 Thread Murray Cumming
Doing this
  boost::python::object obj = get_some_object();
  if(obj)
  {
 //do something
  }
seems to check a bool value inside the underlying PyObject, though I
guess that could throw an exception if it doesn't contain actually
contain a bool. Is that right?
The reference documentation is not very clear about this:
http://www.boost.org/doc/libs/1_42_0/libs/python/doc/v2/object.html


I had wrongly guessed that it would check if the underlying PyObject*
was 0. I did this because I had wrapped a PyObject* in a
boost::python::object for convenience, without checking for 0 first.

Is there any correct way to check, other than doing
  if(obj.ptr())
?


And what's the correct way to check for PyNone other than 
  if (obj == boost::python::object())
?

-- 
[email protected]
www.murrayc.com
www.openismus.com

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Executing python code from C++

2010-02-07 Thread Stefan Seefeld

On 02/07/2010 05:22 AM, Murray Cumming wrote:

In Glom, to execute arbitrary Python code, I use PyRun_String() to parse
the Python code, PyDict_GetItemString() and PyObject_Call() to get a
callable object for that code, and then PyObject_CallObject() to
actually execute the code and get a return value. This was the result of
experimentation and code archeology:
http://git.gnome.org/browse/glom/tree/glom/python_embed/glom_python.cc?h=glom-1-12#n269

Is there anything in boost::python that wraps this, so I can make the
code nicer?
   


Yes. Please read the Boost.Python documentation, specifically on Embedding:
http://www.boost.org/doc/libs/1_42_0/libs/python/doc/tutorial/doc/html/python/embedding.html

Stefan

--

  ...ich hab' noch einen Koffer in Berlin...

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Executing python code from C++

2010-02-07 Thread Murray Cumming
On Sun, 2010-02-07 at 08:03 -0500, Stefan Seefeld wrote:
> On 02/07/2010 05:22 AM, Murray Cumming wrote:
> > In Glom, to execute arbitrary Python code, I use PyRun_String() to parse
> > the Python code, PyDict_GetItemString() and PyObject_Call() to get a
> > callable object for that code, and then PyObject_CallObject() to
> > actually execute the code and get a return value. This was the result of
> > experimentation and code archeology:
> > http://git.gnome.org/browse/glom/tree/glom/python_embed/glom_python.cc?h=glom-1-12#n269
> >
> > Is there anything in boost::python that wraps this, so I can make the
> > code nicer?
> >
> 
> Yes. Please read the Boost.Python documentation, specifically on Embedding:
> http://www.boost.org/doc/libs/1_42_0/libs/python/doc/tutorial/doc/html/python/embedding.html

Thanks.

So, I guess I can use boost::python::exec() to call code that defines a
Python function.

But how can I get a boost::python::object for the (callable object of)
the function? In C, I'm using PyDict_GetItemString() for that.

-- 
[email protected]
www.murrayc.com
www.openismus.com

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Executing python code from C++

2010-02-07 Thread Stefan Seefeld

On 02/07/2010 08:29 AM, Murray Cumming wrote:

So, I guess I can use boost::python::exec() to call code that defines a
Python function.
   


bpl::exec() executes a chunk of Python code, no matter what it contains.


But how can I get a boost::python::object for the (callable object of)
the function? In C, I'm using PyDict_GetItemString() for that.
   


Sorry, I don't understand the question. Can you give an example of what 
you want to do ? May be you want to "exec" some python code that defines 
a function, which you then want to extract and call later ?

That may look like this:

  // Retrieve the main module
  bpl::object main = bpl::import("__main__");
  // Retrieve the main module's namespace
  bpl::object global(main.attr("__dict__"));
  // Define the 'embedded' Python code...
  std::string py_code = "def greeting(): print 'hello world !'";
  // ...and execute it.
  bpl::object result = bpl::exec(py_code, global, global);
  // Extract the function
  bpl::object greeting = global["greeting"];
  // Call it
  greeting();

You may combine this with the other techniques outlines previously. For 
example, your Python code may define types based on previously exported 
C++ types (Python classes derived from C++ classes, say), and then 
extract them to gain back C++ references to base classes. There are 
endless possibilities to play with such hybrid code... :-)


Stefan

--

  ...ich hab' noch einen Koffer in Berlin...

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


[C++-sig] ANN: PyBindGen 0.14

2010-02-07 Thread Gustavo Carneiro
PyBindGen is a Python module that is geared to generating C/C++ code that
binds a C/C++ library for Python. It does so without extensive use of either
C++ templates or C pre-processor macros. It has modular handling of C/C++
types, and can be easily extended with Python plugins. The generated code is
almost as clean as what a human programmer would write.

It can be downloaded from:

http://code.google.com/p/pybindgen/

Bug reports should be filed here:

https://bugs.launchpad.net/ 
pybindgen 

Documentation:

http://packages.python.org/PyBindGen/

NEWS:

=== pybindgen 0.14 ===

- Multiple inheritance support

- Virtual methods can now be overridden with Method instead of _Method

- Add annotation support for instance attributes

- Benchmarks (vs Boost.Python, SWIG, and SIP)

- New types supported: int16_t& and std::string* parameter types

- Non-virtual protected methods are now also wrapped

- Wrap enum pointer params

Note: this release marks the beginning of a transition to a minor change
in the API of the generated bindings.

Prior to PyBindGen version 0.14, the code generated to handle C++
virtual methods required Python user code to define a _foo method in
order to implement the virtual method foo.  Since 0.14, PyBindGen
changed so that virtual method foo is implemented in Python by
defining a method foo, i.e. no underscore prefix is needed anymore.
Setting pybindgen.settings.deprecated_virtuals to True will force the
old virtual method behaviour.  But this is really deprecated; newer
code should set pybindgen.settings.deprecated_virtuals to False.

In PyBindGen 0.14, if the option
pybindgen.settings.deprecated_virtuals is not set, PyBindGen emits a
warning and assumes the value of True in order to preserve backward
compatibility.  In PyBindGen 0.15, the default value of this option
will change to False, and in 0.16 the support for deprecated virtuals
will be removed.

This change was made to make the user code interface more intuitive,
and to align it with other Python bindings tools such as SIP,
Boost.Python, and SWIG.

-- 
Gustavo J. A. M. Carneiro
INESC Porto, UTM, WiN, http://win.inescporto.pt/gjc
"The universe is always one step beyond logic." -- Frank Herbert
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig

Re: [C++-sig] ANN: PyBindGen 0.14

2010-02-07 Thread Neal Becker
PyBindGen shows an example wrapping STL containers.  What if I need to wrap 
my own containers?  Is there some generic container machinery?

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Executing python code from C++

2010-02-07 Thread Murray Cumming
On Sun, 2010-02-07 at 09:51 -0500, Stefan Seefeld wrote:
> 
> Sorry, I don't understand the question. Can you give an example of
> what 
> you want to do ? May be you want to "exec" some python code that
> defines 
> a function, which you then want to extract and call later ?
> That may look like this:
> 
>// Retrieve the main module
>bpl::object main = bpl::import("__main__");
>// Retrieve the main module's namespace
>bpl::object global(main.attr("__dict__"));
>// Define the 'embedded' Python code...
>std::string py_code = "def greeting(): print 'hello world !'";
>// ...and execute it.
>bpl::object result = bpl::exec(py_code, global, global);
>// Extract the function
>bpl::object greeting = global["greeting"]; 

Yes, this last line is what I figured out from some other example code.
It does work for me. Thanks.

I guess it make sense in terms of the weird Python C API, but it's all
far from obvious without knowledge of that.

Thanks again.

-- 
[email protected]
www.murrayc.com
www.openismus.com

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


[C++-sig] boost::python and Date/Time values

2010-02-07 Thread Murray Cumming
Is there any easy way to get python Date, Time and DateTime values from
boost::python::objects? In C, I'm using PyDateTime_GET_YEAR(),
PyDateTime_GET_MONTH(), PyDateTime_GET_DAY(), etc, but it would be nice
to use some C++ API for this.

-- 
[email protected]
www.murrayc.com
www.openismus.com

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Executing python code from C++

2010-02-07 Thread Stefan Seefeld

On 02/07/2010 04:51 PM, Murray Cumming wrote:

On Sun, 2010-02-07 at 09:51 -0500, Stefan Seefeld wrote:
   

Sorry, I don't understand the question. Can you give an example of
what
you want to do ? May be you want to "exec" some python code that
defines
a function, which you then want to extract and call later ?
That may look like this:

// Retrieve the main module
bpl::object main = bpl::import("__main__");
// Retrieve the main module's namespace
bpl::object global(main.attr("__dict__"));
// Define the 'embedded' Python code...
std::string py_code = "def greeting(): print 'hello world !'";
// ...and execute it.
bpl::object result = bpl::exec(py_code, global, global);
// Extract the function
bpl::object greeting = global["greeting"];
 

Yes, this last line is what I figured out from some other example code.
It does work for me. Thanks.

I guess it make sense in terms of the weird Python C API, but it's all
far from obvious without knowledge of that.
   


I think this has nothing to do with the C API, but rather the way the 
"exec" builtin function is defined (i.e., within Python itself): It 
executes some Python code within the context of a 'global' and a 'local' 
namespace which may be provided to the "exec" call. It also returns an 
object, but that is in general rather useless (only useful for 
error-checkin inside the C API). The real effects of the invocation are 
to be found in the 'global' and 'local' namespaces, whose content may 
have changed...



Thanks again.
   


You are welcome.

Stefan


--

  ...ich hab' noch einen Koffer in Berlin...

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] ANN: PyBindGen 0.14

2010-02-07 Thread Gustavo Carneiro
On Sun, Feb 7, 2010 at 8:57 PM, Neal Becker  wrote:

> PyBindGen shows an example wrapping STL containers.  What if I need to wrap
> my own containers?  Is there some generic container machinery?
>

Yes, there is some generic container machinery, although it currently is
duplicating the STL container machinery.  I hope some day to converge the
two, so that STL container support code simply uses the generic code, but I
have not found motivation to do it yet.

The generic container support can be used to add container powers to any
user class, and can be seen in the unit tests module, file tests/foo.h,
classes VectorLike, VectorLike2, and MapLike.

The class VectorLike registers methods for getitem/setitem/len slots (see
tests/foomodulegen.py):

VectorLike.add_method('get_item', 'double', [Parameter.new('size_t',
'index')], custom_name='__getitem__')
VectorLike.add_method('set_item', 'void', [Parameter.new('size_t',
'index'), Parameter.new('double', 'value')],
  custom_name='__setitem__')
VectorLike.add_method('get_len', 'size_t', [], custom_name='__len__')

The class VectorLike2 instead of the above slots defines begin/end methods
and uses iterators (see tests/foomodulegen_common.py).  The tp_iter slot is
defined:

VectorLike2.add_container_traits(ReturnValue.new('double'),
begin_method='Begin', end_method='End', iterator_type='Iterator')

The class MapLike implements the "mapping protocol":

MapLike.add_container_traits((ReturnValue.new('int'),
ReturnValue.new('double')),
 begin_method='Begin', end_method='End',
iterator_type='Iterator',
 is_mapping=True)


I'm sorry for the lack of examples and documentation.  Anyway, I hope this
helps.

Regards.

-- 
Gustavo J. A. M. Carneiro
INESC Porto, UTM, WiN, http://win.inescporto.pt/gjc
"The universe is always one step beyond logic." -- Frank Herbert
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig

Re: [C++-sig] Checking for or null PyObject* or PyNone

2010-02-07 Thread Jim Bosch
On Sun, 2010-02-07 at 11:47 +0100, Murray Cumming wrote:
> Doing this
>   boost::python::object obj = get_some_object();
>   if(obj)
>   {
>  //do something
>   }
> seems to check a bool value inside the underlying PyObject, though I
> guess that could throw an exception if it doesn't contain actually
> contain a bool. Is that right?
> The reference documentation is not very clear about this:
> http://www.boost.org/doc/libs/1_42_0/libs/python/doc/v2/object.html
> 
> 
> I had wrongly guessed that it would check if the underlying PyObject*
> was 0. I did this because I had wrapped a PyObject* in a
> boost::python::object for convenience, without checking for 0 first.
> 

I believe the checking happens typically in boost::python::handle, which
is an intermediate between PyObject* and boost::python::object.  When
you construct a handle, you can pass wrap it with null_ok if you don't
want it to throw on NULL; otherwise I think it would.  How are you
making the boost::python::object?  I always construct a handle first.

> Is there any correct way to check, other than doing
>   if(obj.ptr())
> ?
> 
> 
> And what's the correct way to check for PyNone other than 
>   if (obj == boost::python::object())
> ?
> 

I think that's the standard way.  I suppose

if (obj.ptr() == Py_None)

might be faster on some compilers, but it's almost certainly not worth
worrying about.


Jim Bosch


___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Checking for or null PyObject* or PyNone

2010-02-07 Thread Stefan Seefeld

On 02/07/2010 09:32 PM, Jim Bosch wrote:

On Sun, 2010-02-07 at 11:47 +0100, Murray Cumming wrote:

And what's the correct way to check for PyNone other than
   if (obj == boost::python::object())
?

 

I think that's the standard way.  I suppose

if (obj.ptr() == Py_None)

might be faster on some compilers, but it's almost certainly not worth
worrying about.
   


if (obj) ...

is definitely the right way to do it.

Stefan

--

  ...ich hab' noch einen Koffer in Berlin...

___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] Checking for or null PyObject* or PyNone

2010-02-07 Thread Ralf W. Grosse-Kunstleve
> if (obj) ...

> 
> is definitely the right way to do it.

Sorry to correct, but it isn't equivalent to "obj is None".
if (obj) uses PyObject_IsTrue(); see
boost/python/object_operators.hpp line 60.

I'll add

  obj.is_none()

and

  obj.is_not_none()

when I get a chance.

Ralf
___
Cplusplus-sig mailing list
[email protected]
http://mail.python.org/mailman/listinfo/cplusplus-sig