Re: [C++-sig] [Boost.Python] tutorial python extension fails on import with ImportError: No module named hello_ext
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
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
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
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
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
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