Re: [C++-sig] [Boost.Python] tutorial python extension fails on import with ImportError: No module named hello_ext

2010-02-10 Thread TP
I know this is a little late, but I just started using Boost.Python on
Windows XP, and saw the same exact problems as the original poster so
I thought I should give a solution since no one else has (and I've
seen the same question go unanswered elsewhere).

On 11/10/2009 10:36 PM, Charles Lentz wrote:

> When using boost_1_38_0\libs\python\example\tutorial, I try to import the
> extension that is created (hello_ext) but get the exception, ImportError: No
> module named hello_ext

> I modify Jamroot so that the last few lines where it creates tests are
> commented out.  When I run bjam again, hello_ext.pyd remains (previously it
> was being created, used for the test, and then deleted).  I try to run
> hello.py (which is the script that the test uses) from IDLE (which comes
> with the installation of python) and it throws an exception for my import
> statement

As others note elsewhere you can instead add "--preserve-test-targets"
to your bjam command line. Also adding "-d+2" lets you see more
verbose output of what bjam is doing behind the scenes.

>
> Traceback (most recent call last):
>
>  File
> "C:\Users\Charles\Desktop\boost_1_38_0\boost_1_38_0\libs\python\example\tuto
> rial\hello.py", line 6, in 

>import hello_ext
>
> ImportError: No module named hello_ext
>
> Hrmm.  Okay.  So I move the hello.py file into the same directory as the
> hello_ext.pyd file.  Run it again using IDLE, still get the exception
>

After much googling and looking at the bjam output with "-d+2" turned
on, I discovered that the problem is not just with the location (and
existence) of hello_ext.pyd.

Not only does hello_ext.pyd have to be somewhere in your PATH (copying
it to the same dir as hello.py solves that problem), but the
Boost.Python dll ALSO has to be in the path. In my case I had to add
C:\boost_1_42_0\stage\lib to my PATH.

Of course, this is obvious after the fact. However, the error message
is confusing. What it really means in this case is:

  Can't find boost_python-vc90-mt-1_42.dll or
  boost_python-vc90-mt-gd-1_42.dll.

In addition the "Getting Started on Windows" page at
http://www.boost.org/doc/libs/1_42_0/more/getting_started/windows.html
NEVER mentions having to add C:\boost_1_42_0\stage\lib to the PATH if
you compile the library yourself.

I imagine this doesn't come up more often because most people
initially use the pre-built binaries from BoostPro Computing, and that
installer probably correctly sets the PATH.

I also had problems running bjam since I had copied the tutorial to my
F: drive. I was getting:

  Unable to load Boost.Build: could not find "boost-build.jam"
  ---
  Attempted search from F:\Boost\BoostPythonTutorial up to the root

Changing the tutorial's jamroot file to say:

  use-project boost
: C:/boost_1_42_0 ;

didn't help.

I eventually had to copy C:\boost_1_42_0\boost-build.jam to F:\Boost
and comment everything out and add:

  boost-build C:/boost_1_42_0/tools/build/v2 ;

(This last part may not have normally been necessary but I got some
error message about not being able to find a dll when I first ran
bootstrap.bat. I solved that problem by downloading the prebuilt
version of bjam.exe)

Turns out all of this is explained here:

 Knowledge Base/CPP/Boost Python Step By Step
 
http://www.thalesians.com/finance/index.php/Knowledge_Base/CPP/Boost_Python_Step_By_Step#Building_the_Boost.Python_Tutorial_in_Another_Location
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


[C++-sig] [Boost.Python] Wrapping C library functions

2010-02-14 Thread TP
Suppose I am attempting to use a C (not C++) library that has an .h file
with things like this:

 extern PIX * pixCreate ( l_int32 width, l_int32 height, l_int32 depth );
 extern void pixDestroy ( PIX **ppix );

 extern PIX * pixClone ( PIX *pixs );
 extern PIX * pixCopy ( PIX *pixd, PIX *pixs );

Is it possible to use Boost.Python to wrap such functions?

In particular, note that pixDestroy() is going to want the address of the
pointer returned by pixCreate().

(This is from the leptprotos.h file of the Leptonica Image Processing
library at leptonica.com)
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Re: [C++-sig] [Boost.Python] Wrapping C library functions

2010-02-15 Thread TP
On Sun, Feb 14, 2010 at 5:04 PM, Stefan Seefeld  wrote:
> Yes. Do you have the definition of PIX available ? In that case, you could
> use that via class_

Yes. The entire source of the Leptonica C Image Processing Library is
available at http::/leptonica.com.

Could you give a little more detail please?

The part that confuses me at this point is how to handle parameters of
the form PIX** ppix (Leptonica is FULL of parameters like SOMETYPE**
someParm).

> Otherwise, you may want to create a tiny wrapper class for it, such as
>
> class PIXWrapper
> {
> public:
>  PIXWrapper(I_int32 w, I_int32 h, I_int32 d) : pix_(pixCreate(w, h, d) {}
>  ~PIXWrapper() { pixDestroy(&pix_);}
>  ...
> private:
>  PIX *pix_;
> };

I was hoping to not have to write such wrapper classes. But thank you
for the example. From that I can clearly see how to handle the address
of pointer problem if I decide to take this route.
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] [Boost.Python] Wrapping C library functions

2010-02-15 Thread TP
Doesn't the first example in The Boost.Python Tutorial
(http://www.boost.org/doc/libs/1_42_0/libs/python/doc/tutorial/doc/html/index.html)
show it making a simple C function available to Python?

I want to be able to use the open source, Leptonica C Image Processing
Library (available at http::/leptonica.com) from Python, preferably
without having to make any changes to it. But again, handling the
PIX** parameter seems problematic.

I was hoping to avoid writing C++ wrapper classes (but Stefan
Seefeld's answer on this list) does have a nice short example of what
I would have to do.

Using SWIG was my last choice (well, the last choice is directly using
the C Api).

I have also looked at pybindgen, but Gustavo Carneiro tells me at
https://answers.launchpad.net/pybindgen/+question/101056 that it is
currently unable to easily handle parameters of the form SOMETYPE**.

Other options I will investigate are: ctypes, Cython, expy, and SIP
(the last only because the ultiate goal is to use Leptonica Image
Processing routines inside a PyQt-based app).
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] [Boost.Python] Wrapping C library functions

2010-02-15 Thread TP
On Sun, Feb 14, 2010 at 9:31 PM, Roman Yakovenko
 wrote:
> On Mon, Feb 15, 2010 at 2:32 AM, TP  wrote:
>> Suppose I am attempting to use a C (not C++) library that has an .h file
>> with things like this:
>>
>>  extern PIX * pixCreate ( l_int32 width, l_int32 height, l_int32 depth );
>>  extern void pixDestroy ( PIX **ppix );
>>
>>  extern PIX * pixClone ( PIX *pixs );
>>  extern PIX * pixCopy ( PIX *pixd, PIX *pixs );
>>
>> Is it possible to use Boost.Python to wrap such functions?
>
> Definitely, but the price will be too high.
>
> If the library coded in "C" only than you can use ctypes module to
> access the functionality. You will get pure-Python solution.
> There are even few code generators out there, that will happily
> generate initial ctypes code for you.
>
> --
> Roman Yakovenko
> C++ Python language binding
> http://www.language-binding.net/
> ___
> Cplusplus-sig mailing list
> Cplusplus-sig@python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>

Thank you for your response. ctypes was on my list of options to
investigate. I wonder if you know if it will be able to handle
parameters like PIX** ppix?

A generator would be nice, as the Leptonica Image Processing Library
is quite large (although my initial plans are to do as few functions
as possible, just to see what's involved in making this work).
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig


Re: [C++-sig] [Boost.Python] Wrapping C library functions

2010-02-15 Thread TP
On Mon, Feb 15, 2010 at 1:41 PM, Stefan Seefeld  wrote:
> On 02/15/2010 04:26 PM, TP wrote:
>>
>> On Sun, Feb 14, 2010 at 5:04 PM, Stefan Seefeld
>>  wrote:
>>
>>>
>>> Yes. Do you have the definition of PIX available ? In that case, you
>>> could
>>> use that via class_
>>>
>>
>> Yes. The entire source of the Leptonica C Image Processing Library is
>> available at http::/leptonica.com.
>>
>> Could you give a little more detail please?
>>
>
> If PIX is a known type (as opposed to an opaque pointer), you can wrap that
> directly, instead of having to use an indirection.
> However, you still need to find a way to specify how PIX objects are to be
> constructed and destroyed, and thus, you need to store PIX inside Python
> objects via pointers that allow custom destructors (such as
> boost::shared_ptr).
>
> I bet, all things considered, a wrapper class such as the one I proposed in
> my previous mail is still the best way forward, as it best encapsulates how
> PIX objects get constructed (incl. cloned) and destructed.
>
> Memory management is by far the most complex aspect of wrapping C and C++
> libraries in Python. And if your library mostly operates on raw pointers,
> you really need to be careful about object lifetime, argument and return
> value ownership, etc.
>
>
> Regards,
>Stefan
>
> --
>
>  ...ich hab' noch einen Koffer in Berlin...
>
> ___
> Cplusplus-sig mailing list
> Cplusplus-sig@python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>

While the definition of a PIX is available, Leptonica users are
supposed to use the supplied functions to access "attributes" (things
like pixGetWidth(), pixSetWidth(), etc). See
http://leptonica.com/library-notes.html#PIX for brief details.

Since images can be large, Leptonica goes to great lengths to avoid
copying them if possible so memory management is crucial. The PIX are
reference counted, and it is up to the caller to make sure they use
pixDestroy() at the right times.

>From pix1.c:

(2) The protocol to be used is:
(a) Whenever you want a new handle to an existing image,
call pixClone(), which just bumps a ref count.
(b) Always call pixDestroy() on all handles.  This
decrements the ref count, nulls the handle, and
only destroys the pix when pixDestroy() has been
called on all handles.

I probably should have picked a simpler library for my first foray
into hooking C/C++ to Python :)

I'm hoping I can initially do small pieces at a time as I need them.
___
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig