Thread: [ctypes-users] Dereferencing a pointer
Brought to you by:
theller
|
From: Bryan D R. <bdr...@ju...> - 2004-06-28 02:18:49
|
I am currently working with pyFMOD (python extensions to FMOD, a sound
library) to add callback functionality to the python library. Several
functions in FMOD/pyFMOD return void pointers, notably the callback
functions
FOUND_STREAMCALLBACK
Callback used with user streams.
signed char FOUND_STREAMCALLBACK(
FOUND_STREAM *stream,
void *buff,
int len,
int param
);
FOUND_DSPCALLBACK
Callback definition for DSP units.
void *FSOUND_DSPCALLBACK(
void *originalbuffer,
void *newbuffer,
int length,
int param
);
Here is my callback code which is located in pyFMOD
#Bryan's Callback Code:
_FSOUND_DSPCALLBACK = CFUNCTYPE(c_void_p, pointer(c_int), pointer(c_int),
c_int, c_int)
_FSOUND_STREAMCALLBACK = CFUNCTYPE(c_byte, c_int, c_void_p, c_int, c_int)
_FSOUND_ALLOCCALLBACK = CFUNCTYPE(c_void_p, c_uint)
_FSOUND_REALLOCCALLBACK = CFUNCTYPE(c_void_p, c_void_p, c_uint)
_FSOUND_READCALLBACK = CFUNCTYPE(c_int, c_void_p, c_int, c_uint)
_FSOUND_TELLCALLBACK = CFUNCTYPE(c_int, c_uint)
#The next function had a void return type. I'm not sure how to do that
in ctypes.
#If this doesn't work, I'll try posting to the mailing list.
_FSOUND_FREECALLBACK = CFUNCTYPE(c_void_p, c_void_p)
#The next function should return void as well.
_FSOUND_CLOSECALLBACK = CFUNCTYPE(c_void_p, c_uint)
#This function uses a signed character for input 3, the last one.
#Not sure if c_byte is the correct type or not.
_FSOUND_SEEKCALLBACK = CFUNCTYPE(c_int, c_uint, c_int, c_byte)
#This function used a signed character as well.
_FSOUND_OPENCALLBACK = CFUNCTYPE(c_uint, c_char_p)
This is the code I am trying to run and get the error with
import pyFMOD
from ctypes import *
def myDSP_Callback(originalbuffer, newbuffer, length, param):
print "timmy"
originalbuffer.contents
pyFMOD.FSOUND_Init(44100, 32, 0);
s = pyFMOD.FSOUND_Stream_OpenFile(".\\forkbomb.ogg", pyFMOD.FSOUND_2D, 0)
a = pyFMOD.FSOUND_Stream_CreateDSP(s, myDSP_Callback, 301, 0)
pyFMOD.FSOUND_DSP_SetActive(a, True)
pyFMOD.FSOUND_Stream_Play(0, s)
print "started"
for i in range(1000000):
pass
print "stopped"
pyFMOD.FSOUND_Stream_Stop(s)
This is the error I get
Traceback (most recent call last):
File "C:\Source\Python\pyDanceR\fmodTest.py", line 1, in ?
import pyFMOD
File "C:\PYTHON23\lib\site-packages\pyFMOD.py", line 6, in ?
_FSOUND_DSPCALLBACK = CFUNCTYPE(c_void_p, pointer(c_int),
pointer(c_int), c_int, c_int)
File "C:\PYTHON23\Lib\site-packages\ctypes\__init__.py", line 206, in
pointer
return POINTER(type(inst))(inst)
File "C:\PYTHON23\Lib\site-packages\ctypes\__init__.py", line 189, in
POINTER
{'_type_': cls})
TypeError: _type_ must have storage info
How do I acess and modify the pointer original buffer? I know it's
length(from a function) and size(It is set to 32 or 16 bit depending on
the processor.). |
|
From: Thomas H. <th...@py...> - 2004-07-06 20:10:51
|
Bryan D Rosander <bdr...@ju...> writes:
> I am currently working with pyFMOD (python extensions to FMOD, a sound
> library) to add callback functionality to the python library. Several
> functions in FMOD/pyFMOD return void pointers, notably the callback
> functions
[...]
> #The next function had a void return type. I'm not sure how to do that
> in ctypes.
With ctypes CVS, you could use None as return type. Doesn't work in
0.6.3, but you can probably use c_int instead, and ignore the result.
> This is the error I get
> Traceback (most recent call last):
> File "C:\Source\Python\pyDanceR\fmodTest.py", line 1, in ?
> import pyFMOD
> File "C:\PYTHON23\lib\site-packages\pyFMOD.py", line 6, in ?
> _FSOUND_DSPCALLBACK = CFUNCTYPE(c_void_p, pointer(c_int),
> pointer(c_int), c_int, c_int)
> File "C:\PYTHON23\Lib\site-packages\ctypes\__init__.py", line 206, in
> pointer
> return POINTER(type(inst))(inst)
> File "C:\PYTHON23\Lib\site-packages\ctypes\__init__.py", line 189, in
> POINTER
> {'_type_': cls})
> TypeError: _type_ must have storage info
Somewhat similar problem as another poster had: pointer() is a function
creating instances of ctypes' types. So, pointer(c_int) throws an
error, you should use pointer(c_int(32)) to create an instance of a
pointer pointing to the integer 32.
But, in the CFUNCTYPE call, you need ctypes' types, not ctypes'
instances. That's what POINTER creates:
_FSOUND_DSPCALLBACK = CFUNCTYPE(c_void_p, POINTER(c_int), c_int, c_int)
Hope that helps,
Thomas
|
|
From: Holger D. <H.D...@gm...> - 2004-07-09 11:10:07
|
On a related note:
I am currently trying to wrap a function which allocates a buffer for
me; something like
,----
| int foo(char **out_buffer, size_t *out_buffer_length);
`----
The data in the buffer can be binary, i.e. it may contain a 0-byte,
which is why we get a length returned as well.
Because of the 0-byte, I cannot use something like
,----
| out_buffer = c_char_p()
| out_buffer_length = c_int()
| success = the_lib.foo(byref(out_buffer), byref(out_buffer_length))
`----
What I currently have is:
,----
| out_buffer = POINTER(c_char)()
| out_buffer_length = c_int()
| success = the_lib.foo(pointer(out_buffer), byref(out_buffer_length))
| out_buffer = "".join([out_buffer[i] for i in range(out_buffer_length)])
`----
and this works.
Two questions:
a) Could this be done better?
b) Why doesn't the pointer metaclass support slicing? I.e. this could
have simplified my last line to
,----
| out_buffer = "".join(out_buffer[:out_buffer_length])
`----
I had a quick glance at the code and it is just missing -- is this
intentional or just not yet done?
Thanks,
Holger
|
|
From: Thomas H. <th...@py...> - 2004-07-09 20:08:54
|
Holger Duerer <H.D...@gm...> writes: > I am currently trying to wrap a function which allocates a buffer for > me; something like > ,---- > | int foo(char **out_buffer, size_t *out_buffer_length); > `---- > > The data in the buffer can be binary, i.e. it may contain a 0-byte, > which is why we get a length returned as well. > > Because of the 0-byte, I cannot use something like > > ,---- > | out_buffer = c_char_p() > | out_buffer_length = c_int() > | success = the_lib.foo(byref(out_buffer), byref(out_buffer_length)) > `---- > > What I currently have is: > ,---- > | out_buffer = POINTER(c_char)() > | out_buffer_length = c_int() > | success = the_lib.foo(pointer(out_buffer), byref(out_buffer_length)) > | out_buffer = "".join([out_buffer[i] for i in range(out_buffer_length)]) > `---- > and this works. > > Two questions: > a) Could this be done better? No, it's the 'correct' way to do it, but let me make two remarks. You could use byref(out_buffer) in the the_lib.foo call instead of pointer(out_buffer), this will be slightly faster. And it seems in your code the pointer can never be freed because you overwrite the out_buffer variable. Maybe you were just simplifying... > b) Why doesn't the pointer metaclass support slicing? I.e. this could > have simplified my last line to > ,---- > | out_buffer = "".join(out_buffer[:out_buffer_length]) > `---- > I had a quick glance at the code and it is just missing -- is this > intentional or just not yet done? I probably had a mental block (Brett vor'm Kopf) because I always thought about slicing support for arrays instead of pointers first. And I couldn't decide if it would be better to return a new ctypes array instance as the slice, or a list of array elements. The array instance would be much more complicated, because this would have to be an instance of a probably not yet existing class. For pointer slicing, it is simpler because an array would not make any sense. So I think the list of elements is what needs to be returned, for pointers *and* for arrays. Same for slice assignment, of course. Oh, and for arrays or pointers of c_chars it could be specialized to return a string instead of a list of characters instead, so that you could write ,---- | out_buffer = out_buffer[:out_buffer_length] `---- instead of the join above. Sounds good? Thanks, Thomas |