How to correctly pass “pointer-to-pointer” into DLL via ctypes?

Discussion in 'Python' started by Grigory Petrov, Nov 18, 2010.

  1. Hello.

    I have a DLL that allocates memory and returns it. Function in DLL is like this:

    void Foo( unsigned char** ppMem, int* pSize )
    {
      * pSize = 4;
      * ppMem = malloc( * pSize );
      for( int i = 0; i < * pSize; i ++ ) (* pMem)[ i ] = i;
    }

    Also, i have a python code that access this function from my DLL:

    from ctypes import *
    Foo = windll.mydll.Foo
    Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    mem = POINTER( c_ubyte )()
    size = c_int( 0 )
    Foo( byref( mem ), byref( size ) ]
    print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]

    I'm expecting that print will show "4 0 1 2 3" but it shows "4 221 221
    221 221" O_O. Any hints what i'm doing wrong?
     
    Grigory Petrov, Nov 18, 2010
    #1
    1. Advertising

  2. Re: How to correctly pass “pointer-to-pointer†into DLL via ctypes?

    Grigory Petrov <> writes:

    > Hello.
    >
    > I have a DLL that allocates memory and returns it. Function in DLL is like this:
    >
    > void Foo( unsigned char** ppMem, int* pSize )
    > {
    >   * pSize = 4;
    >   * ppMem = malloc( * pSize );
    >   for( int i = 0; i < * pSize; i ++ ) (* pMem)[ i ] = i;
    > }
    >
    > Also, i have a python code that access this function from my DLL:
    >
    > from ctypes import *
    > Foo = windll.mydll.Foo
    > Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    > mem = POINTER( c_ubyte )()
    > size = c_int( 0 )
    > Foo( byref( mem ), byref( size ) ]
    > print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
    >
    > I'm expecting that print will show "4 0 1 2 3" but it shows "4 221 221
    > 221 221" O_O. Any hints what i'm doing wrong?


    After correcting quite a few obvious errors in your code, it worked just
    fine for me. So I guess what you think you test is not what you test.

    --- test.py
    from ctypes import *

    foo = cdll.LoadLibrary("/Users/deets/projects/GH28/kinect/kinect/c/foo/libtest.dylib").foo
    foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    mem = POINTER( c_ubyte )()
    size = c_int( 0 )
    foo( byref( mem ), byref( size ) )
    print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
    ---

    --- test.c
    void foo( unsigned char** ppMem, int* pSize )
    {
    int i;
    * pSize = 4;
    * ppMem = malloc( * pSize );
    for( i = 0; i < * pSize; i ++ ) (* ppMem)[ i ] = i;
    }
    ---

    --- CMakeLists.txt
    cmake_minimum_required (VERSION 2.6)
    project (Test)
    add_library(test SHARED test.c)
    ---

    --
    Diez
     
    Diez B. Roggisch, Nov 19, 2010
    #2
    1. Advertising

  3. Thank you a lot!

    I have stripped down my production code to the sample - and it worked.
    Bug was in another part of my code where free() was called for the
    memory in question.

    On Fri, Nov 19, 2010 at 3:39 PM, Diez B. Roggisch <> wrote:
    > Grigory Petrov <> writes:
    >
    >> Hello.
    >>
    >> I have a DLL that allocates memory and returns it. Function in DLL is like this:
    >>
    >> void Foo( unsigned char** ppMem, int* pSize )
    >> {
    >>   * pSize = 4;
    >>   * ppMem = malloc( * pSize );
    >>   for( int i = 0; i < * pSize; i ++ ) (* pMem)[ i ] = i;
    >> }
    >>
    >> Also, i have a python code that access this function from my DLL:
    >>
    >> from ctypes import *
    >> Foo = windll.mydll.Foo
    >> Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    >> mem = POINTER( c_ubyte )()
    >> size = c_int( 0 )
    >> Foo( byref( mem ), byref( size ) ]
    >> print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
    >>
    >> I'm expecting that print will show "4 0 1 2 3" but it shows "4 221 221
    >> 221 221" O_O. Any hints what i'm doing wrong?

    >
    > After correcting quite a few obvious errors in your code, it worked just
    > fine for me. So I guess what you think you test is not what you test.
    >
    > --- test.py
    > from ctypes import *
    >
    > foo = cdll.LoadLibrary("/Users/deets/projects/GH28/kinect/kinect/c/foo/libtest.dylib").foo
    > foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    > mem = POINTER( c_ubyte )()
    > size = c_int( 0 )
    > foo( byref( mem ), byref( size ) )
    > print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
    > ---
    >
    > --- test.c
    > void foo( unsigned char** ppMem, int* pSize )
    > {
    >  int i;
    >  * pSize = 4;
    >  * ppMem = malloc( * pSize );
    >  for( i = 0; i < * pSize; i ++ ) (* ppMem)[ i ] = i;
    > }
    > ---
    >
    > --- CMakeLists.txt
    > cmake_minimum_required (VERSION 2.6)
    > project (Test)
    > add_library(test SHARED test.c)
    > ---
    >
    > --
    > Diez
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >
     
    Grigory Petrov, Nov 19, 2010
    #3
  4. Grigory Petrov

    Guest

    On Thursday, November 18, 2010 8:03:57 PM UTC+8, Grigory Petrov wrote:
    > Hello.
    >
    > I have a DLL that allocates memory and returns it. Function in DLL is like this:
    >
    > void Foo( unsigned char** ppMem, int* pSize )
    > {
    >   * pSize = 4;
    >   * ppMem = malloc( * pSize );
    >   for( int i = 0; i < * pSize; i ++ ) (* pMem)[ i ] = i;
    > }
    >
    > Also, i have a python code that access this function from my DLL:
    >
    > from ctypes import *
    > Foo = windll.mydll.Foo
    > Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    > mem = POINTER( c_ubyte )()
    > size = c_int( 0 )
    > Foo( byref( mem ), byref( size ) ]
    > print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
    >
    > I'm expecting that print will show "4 0 1 2 3" but it shows "4 221 221
    > 221 221" O_O. Any hints what i'm doing wrong?


    I am wondering in Python how you free the memory which is allocated in yourDLL ?
    Thanks
     
    , Oct 27, 2012
    #4
  5. Grigory Petrov

    Guest

    On Thursday, November 18, 2010 8:03:57 PM UTC+8, Grigory Petrov wrote:
    > Hello.
    >
    > I have a DLL that allocates memory and returns it. Function in DLL is like this:
    >
    > void Foo( unsigned char** ppMem, int* pSize )
    > {
    >   * pSize = 4;
    >   * ppMem = malloc( * pSize );
    >   for( int i = 0; i < * pSize; i ++ ) (* pMem)[ i ] = i;
    > }
    >
    > Also, i have a python code that access this function from my DLL:
    >
    > from ctypes import *
    > Foo = windll.mydll.Foo
    > Foo.argtypes = [ POINTER( POINTER( c_ubyte ) ), POINTER( c_int ) ]
    > mem = POINTER( c_ubyte )()
    > size = c_int( 0 )
    > Foo( byref( mem ), byref( size ) ]
    > print size, mem[ 0 ], mem[ 1 ], mem[ 2 ], mem[ 3 ]
    >
    > I'm expecting that print will show "4 0 1 2 3" but it shows "4 221 221
    > 221 221" O_O. Any hints what i'm doing wrong?


    I am wondering in Python how you free the memory which is allocated in yourDLL ?
    Thanks
     
    , Oct 27, 2012
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Henk Punt
    Replies:
    0
    Views:
    424
    Henk Punt
    Jul 23, 2004
  2. Adam Twardoch
    Replies:
    1
    Views:
    381
    Peter Hansen
    Jul 6, 2005
  3. subopt inTheVicinityOf geemail.com

    Trouble loading dll via ctypes

    subopt inTheVicinityOf geemail.com, Jan 29, 2008, in forum: Python
    Replies:
    1
    Views:
    362
    Helmut Jarausch
    Jan 30, 2008
  4. Replies:
    0
    Views:
    535
  5. Scott
    Replies:
    1
    Views:
    452
    Scott
    Jun 19, 2009
Loading...

Share This Page