Python lists typemapped to C arrays

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Python lists typemapped to C arrays

Robert Jones-2
Hi All - can any of you generous souls give me a hint on this one?

I am ultimately trying to call the windows function

long WaitForMultipleObjects(
    long nCount,
    HANDLE *lpHandles,
    int bWaitAll,
    long dwMilliseconds
    );

(Only the first two arguments matter for the moment). To provide
the HANDLEs I have a Python list. I know I have the list properly
populated because I have written this

void writeHandle( HANDLE h ) {
    printf( "HANDLE -> %0x\n", h );
    }

which I have called with this Python code

    for obj in osWaitObjs:
        writeHandle( obj )

and which prints out exactly the values I am expecting.
Now, to call the big function with my list I have written this
typemap

%typemap ( in ) ( long nCount, HANDLE * lpHandles ) {
    int i;
    printf( "typemap (in)( long nCount, HANDLE * lpHandles )\n" );
    if ( ! PyList_Check( $input ) ) {
        PyErr_SetString( PyExc_ValueError, "Expecting a list" );
        return NULL;
    }
    $1 = PyList_Size( $input );
    $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
    printf( "List(" );
    for ( i = 0; i < $1; i ++ ) {
        PyObject * obj = PyList_GetItem( $input, i );
        $2[ i ] = ( HANDLE ) PyInt_AsLong( obj );
        printf( "%0x, ", $2[ i ] );
    }
    $2[ i ] = 0;
    printf( ")\n" );
}

which includes lots of debugging printf's. Unfortunately the values that result
from this conversion are not the values of the HANDLEs. HANDLE is ultimately
defined as a void*. I'm pretty sure my typemap is not right, but I'm not sure how.

Cheers, Rob.
Reply | Threaded
Open this post in threaded view
|

Re: Python lists typemapped to C arrays

Marcelo Matus
Robert Jones wrote:

> Hi All - can any of you generous souls give me a hint on this one?
>
> I am ultimately trying to call the windows function
>
> long WaitForMultipleObjects(
>     long nCount,
>     HANDLE *lpHandles,
>     int bWaitAll,
>     long dwMilliseconds
>     );
>
> (Only the first two arguments matter for the moment). To provide
> the HANDLEs I have a Python list. I know I have the list properly
> populated because I have written this
>
> void writeHandle( HANDLE h ) {
>     printf( "HANDLE -> %0x\n", h );
>     }
>
> which I have called with this Python code
>
>     for obj in osWaitObjs:
>         writeHandle( obj )
>
> and which prints out exactly the values I am expecting.
> Now, to call the big function with my list I have written this
> typemap
>
> %typemap ( in ) ( long nCount, HANDLE * lpHandles ) {
>     int i;
>     printf( "typemap (in)( long nCount, HANDLE * lpHandles )\n" );
>     if ( ! PyList_Check( $input ) ) {
>         PyErr_SetString( PyExc_ValueError, "Expecting a list" );
>         return NULL;
>     }
>     $1 = PyList_Size( $input );
>     $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
>     printf( "List(" );
>     for ( i = 0; i < $1; i ++ ) {
>         PyObject * obj = PyList_GetItem( $input, i );
>         $2[ i ] = ( HANDLE ) PyInt_AsLong( obj );
>         printf( "%0x, ", $2[ i ] );
>     }
>     $2[ i ] = 0;
>     printf( ")\n" );
> }
>
> which includes lots of debugging printf's. Unfortunately the values
> that result
> from this conversion are not the values of the HANDLEs. HANDLE is
> ultimately
> defined as a void*. I'm pretty sure my typemap is not right, but I'm
> not sure how.
>
> Cheers, Rob.

If HANDLE is a void *, then you can't use PyInt_AsLong, you shoud try

  SWIG_ConvertPtr

instead. See the void.swg file in Lib/typemaps (CVS version) for more
details.

Marcelo







-------------------------------------------------------
This SF.Net email is sponsored by the JBoss Inc.  Get Certified Today
Register for a JBoss Training Course.  Free Certification Exam
for All Training Attendees Through End of 2005. For more info visit:
http://ads.osdn.com/?ad_id=7628&alloc_id=16845&op=click
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Python lists typemapped to C arrays

Robert Jones-2
the PyInt_AsLong function wasn't my first choice, I'd already tried
various applications of SWIG_ConvertPtr, but I suspect I'm not getting
the dereferencing quite right. My best stab at SWIG_ConvertPtr is this

    $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
    for ( i = 0; i < $1; i ++ ) {
        PyObject * obj = PyList_GetItem( $input, i );
        HANDLE tmp;
        if ( ( SWIG_ConvertPtr( obj, SWIG_reinterpret_cast( & tmp, void** ), 0, SWIG_POINTER_EXCEPTION | $disown ) ) == -1 ) {
            free( $2 );
            return NULL;
            }
        $2[ i ] = tmp;

but it doesn't work!

Cheers for you help, Rob.
Reply | Threaded
Open this post in threaded view
|

Re: Python lists typemapped to C arrays

Marcelo Matus
Robert Jones wrote:

> the PyInt_AsLong function wasn't my first choice, I'd already tried
> various applications of SWIG_ConvertPtr, but I suspect I'm not getting
> the dereferencing quite right. My best stab at SWIG_ConvertPtr is this
>
>     $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
>     for ( i = 0; i < $1; i ++ ) {
>         PyObject * obj = PyList_GetItem( $input, i );
>         HANDLE tmp;
>         if ( ( SWIG_ConvertPtr( obj, SWIG_reinterpret_cast( & tmp,
> void** ), 0, SWIG_POINTER_EXCEPTION | $disown ) ) == -1 ) {
>             free( $2 );
>             return NULL;
>             }
>         $2[ i ] = tmp;

I see your problem, well, first you are using 1.3.27 or so, right?, but
in any case, your code should look like

    $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
    for ( i = 0; i < $1; i ++ ) {
        PyObject * obj = PyList_GetItem( $input, i );
        HANDLE *tmp;
        if ( ( SWIG_ConvertPtr( obj,  &tmp, 0, SWIG_POINTER_EXCEPTION |
$disown ) ) == -1 ) {
            free( $2 );
            return NULL;
        }
        $2[ i ] = *tmp;

note that 'tmp' should be a pointer, not a 'by value' element.

Marcelo


>
> but it doesn't work!
>
> Cheers for you help, Rob.




-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user
Reply | Threaded
Open this post in threaded view
|

Re: Python lists typemapped to C arrays

Robert Jones-2
Yippeeeeee! That works. Ta muchly.

So, I need to pass swig the address of the address of the handle? Wow - how come?

Ah, but I also see I never allocate the temporary handle object itself, so I take it that swig
sets tmp to point to an already existing object? That object must be buried
somewhere inside PyObject? I think this is starting to make a bit more sense!

I can't recall where I got the reinterpret_cast stuff from, probably some
example somewhere. When would it be appropriate to use that? Would that
be connected with using directors at all?

Rob.

On 23/11/05, Marcelo Matus <[hidden email]> wrote:
Robert Jones wrote:

> the PyInt_AsLong function wasn't my first choice, I'd already tried
> various applications of SWIG_ConvertPtr, but I suspect I'm not getting
> the dereferencing quite right. My best stab at SWIG_ConvertPtr is this
>
>     $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
>     for ( i = 0; i < $1; i ++ ) {
>         PyObject * obj = PyList_GetItem( $input, i );
>         HANDLE tmp;
>         if ( ( SWIG_ConvertPtr( obj, SWIG_reinterpret_cast( & tmp,
> void** ), 0, SWIG_POINTER_EXCEPTION | $disown ) ) == -1 ) {
>             free( $2 );
>             return NULL;
>             }
>         $2[ i ] = tmp;

I see your problem, well, first you are using 1.3.27 or so, right?, but
in any case, your code should look like

    $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
    for ( i = 0; i < $1; i ++ ) {
        PyObject * obj = PyList_GetItem( $input, i );
        HANDLE *tmp;
        if ( ( SWIG_ConvertPtr( obj,  &tmp, 0, SWIG_POINTER_EXCEPTION |
$disown ) ) == -1 ) {
            free( $2 );
            return NULL;
        }
        $2[ i ] = *tmp;

note that 'tmp' should be a pointer, not a 'by value' element.

Marcelo


>
> but it doesn't work!
>
> Cheers for you help, Rob.



Reply | Threaded
Open this post in threaded view
|

Re: Python lists typemapped to C arrays

Marcelo Matus
Robert Jones wrote:

> Yippeeeeee! That works. Ta muchly.
>
> So, I need to pass swig the address of the address of the handle? Wow
> - how come?
>
yeap, because swig only stores pointer values. So, if you want to
retrieve a pointer value
with a parameter, well, you need a pointer to pointer.

> Ah, but I also see I never allocate the temporary handle object
> itself, so I take it that swig
> sets tmp to point to an already existing object? That object must be
> buried
> somewhere inside PyObject? I think this is starting to make a bit more
> sense!
>
Swig uses it owns data type, PySwigObject, to keep the C/C++ pointer value.
That object is not a Long, and it keeps the pointer  internally as a
void * value.

Swig doesn't allocate the object, you preallocate the object when you
call the function,
then swig just get the pointer values you pass to it.

> I can't recall where I got the reinterpret_cast stuff from, probably some
> example somewhere. When would it be appropriate to use that? Would that
> be connected with using directors at all?

SWIG_reinterpret_cast is just a macro for the C++ operator reinterpret_cast.
Always try to avoid using it since it  is dangerous, as you can testify.

Marcelo


>
> Rob.
>
> On 23/11/05, *Marcelo Matus* <[hidden email]
> <mailto:[hidden email]>> wrote:
>
>     Robert Jones wrote:
>
>     > the PyInt_AsLong function wasn't my first choice, I'd already tried
>     > various applications of SWIG_ConvertPtr, but I suspect I'm not
>     getting
>     > the dereferencing quite right. My best stab at SWIG_ConvertPtr
>     is this
>     >
>     >     $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
>     >     for ( i = 0; i < $1; i ++ ) {
>     >         PyObject * obj = PyList_GetItem( $input, i );
>     >         HANDLE tmp;
>     >         if ( ( SWIG_ConvertPtr( obj, SWIG_reinterpret_cast( & tmp,
>     > void** ), 0, SWIG_POINTER_EXCEPTION | $disown ) ) == -1 ) {
>     >             free( $2 );
>     >             return NULL;
>     >             }
>     >         $2[ i ] = tmp;
>
>     I see your problem, well, first you are using 1.3.27 or so,
>     right?, but
>     in any case, your code should look like
>
>         $2 = ( HANDLE * ) malloc( ( $1 + 1 ) * sizeof( HANDLE ) );
>         for ( i = 0; i < $1; i ++ ) {
>             PyObject * obj = PyList_GetItem( $input, i );
>             HANDLE *tmp;
>             if ( ( SWIG_ConvertPtr( obj,  &tmp, 0,
>     SWIG_POINTER_EXCEPTION |
>     $disown ) ) == -1 ) {
>                 free( $2 );
>                 return NULL;
>             }
>             $2[ i ] = *tmp;
>
>     note that 'tmp' should be a pointer, not a 'by value' element.
>
>     Marcelo
>
>
>     >
>     > but it doesn't work!
>     >
>     > Cheers for you help, Rob.
>
>
>



-------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc. Do you grep through log files
for problems?  Stop!  Download the new AJAX search engine that makes
searching your log files as easy as surfing the  web.  DOWNLOAD SPLUNK!
http://ads.osdn.com/?ad_id=7637&alloc_id=16865&op=click
_______________________________________________
Swig-user mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/swig-user