Am I using ctypes correctly? (and where are fprintf's going?)
TP <[email protected]>
| Newsgroups | gmane.comp.python.ctypes |
|---|---|
| Message-ID | <[email protected]> |
>From the Cplusplus-sig, I gathered that instead of Boost.Python I
should use ctypes for the following problem. But let me make sure I'm
using it correctly.
I am calling the C Leptonica Image Processing C Library
(http://leptonica.com) from python.
Within its leptprotos.h file are functions like this:
extern PIX * pixRead ( const char *filename );
extern l_int32 pixGetWidth ( PIX *pix );
extern void pixDestroy ( PIX **ppix );
Using Windows XP, and within a Command Prompt I do this:
python26
>>> import ctypes
>>> leptonica = ctypes.cdll.leptonlib
>>> pixRead = leptonica.pixRead
>>> pixRead.restype = ctypes.c_void_p
>>> pix = pixRead(r"test.tif")
>>> pix
19758552
>>> type(pix)
<type 'int'>
Why isn't the return type of pixRead() a void *?
To change the int to a void *, I have to do:
>>> pix=ctypes.c_void_p(pix)
>>> pix
c_void_p(19758552)
I suppose I could also do:
>>> pix=ctypes.cast(pix, ctypes.c_void_p)
>>> pix
c_void_p(19758552)
Or what I originally was doing:
>>> pix=ctypes.c_void_p()
>>> pix.value = pixRead(r"test.tif")
>>> pix
c_void_p(19758552)
Isn't there some way to get the correct return type back from
pixRead() without having to either convert it after the fact, or
construct a pointer to put the result in?
>>> leptonica.pixGetWidth(pix)
1553 #this is the correct width
>>> pixDestroy = leptonica.pixDestroy
>>> pixDestroy.restype = None
>>> leptonica.pixDestroy(ctypes.byref(pix))
>>> pix
c_void_p(None) #This looks right, pixDestroy() sets the pointer to NULL.
Is this the proper way you are supposed to supply the address of a
pointer that is returned by a C function? Is there a better way?
I notice that if I do the following pixDestroy also seems to work?
pixDestroy.argtypes = [ctypes.POINTER(ctypes.c_void_p)]
>>> r=pixDestroy(pix)
>>> pix
c_void_p(None)
(Although that might be confusing to users since there appears to be
no difference between PIX** and PIX*)
Now that the pix has been destroyed, you shouldn't be able to get its width:
>>> leptonica.pixGetWidth(pix)
-1
This is correct but there also should have been an error message printed out?
The C library is doing this (I think, I haven't actually used the
debugger on it):
sprintf(charbuf, "Error in %s: %s\n", procname, msg);
fprintf(stderr, charbuf, ival);
But I don't see any error message appear in my console window?
Finally, the documentation states for ctypes.util.find_msvcrt():
Windows only: return the filename of the VC runtype library used by
Python, and by the extension modules. If the name of the library
cannot be determined, None is returned.
If you need to free memory, for example, allocated by an extension
module with a call to the free(void *), it is important that you use
the function in the same library that allocated the memory.
>>> import ctypes.util
>>> ctypes.util.find_msvcrt()
'msvcr90.dll'
Does this mean that if I build a Debug version of the Leptonica DLL
(which will use the Debug version of the runtime library,
msvcr90d.dll), that I also have to build and use a Debug version of
Python26?
I tried using leptonlibd.dll with the ActiveState release version of
Python26 and didn't see any immediate error.
------------------------------------------------------------------------------
SOLARIS 10 is the OS for Data Centers - provides features such as DTrace,
Predictive Self Healing and Award Winning ZFS. Get Solaris 10 NOW
http://p.sf.net/sfu/solaris-dev2dev