ctypes: AttributeError: '_FuncPtr' object has no attribute 'PopsClicksDetection'

333 views
Skip to first unread message

Satya Rao

unread,
Dec 14, 2016, 10:08:07 AM12/14/16
to python-cffi
Hi,

 I'm little new to ctypes. Just to give the background of my problem below.
 I have a library called "pops_clicks_detection.dll" and it depends on one more dll called "fft_x86.dll".
 There is function "PopsClicksDetection()" inside "pops_clicks_detection.dll". Here is the function prototype in C++.

PopRetCode PopsClicksDetection( char *filename, float *pop_time, int pop_time_size, int *pop_count )

where PopRetCode is an enum
typedef enum { FILEOPEN_ERROR = -1,
               NO_POPS = 0,
               POPS_DETECTED = 1,
               NO_MEMORY = 2
             } PopRetCode;

I'm trying to call "PopsClicksDetection" function from my python code using ctypes and cffi, but I'm getting following error stack trace.


Traceback (most recent call last):
  File "pops_clicks_detection.py", line 30, in <module>
    pop_click.PopsClicksDetection('E:/fs_work/fruit-salad/resources/glitch2.wav', pop_time, 1024, pop_count)
AttributeError: '_FuncPtr' object has no attribute 'PopsClicksDetection'


Here is my python code to call "PopsClicksDetection()" function.

import ctypes
from enum import IntEnum
from cffi import FFI

ctypes.CDLL("E:/fs_work/fruit-salad/lib/fft_x86.dll")
pc_lib = ctypes.CDLL("E:/fs_work/fruit-salad/lib/pops_clicks_detection.dll")

# Define the types we need.
class CtypesEnum(IntEnum):
"""A ctypes-compatible IntEnum superclass."""
@classmethod
def from_param(cls, obj):
return int(obj)


class PopRetCode(CtypesEnum):
FILEOPEN_ERROR = -1
NO_POPS = 0
POPS_DETECTED = 1
NO_MEMORY = 2

pop_click = pc_lib.PopsClicksDetection
pop_click.argtypes = (ctypes.POINTER(ctypes.c_char), ctypes.POINTER(ctypes.c_float), ctypes.c_int, ctypes.POINTER(ctypes.c_int))
pop_click.restype = PopRetCode

ffi = FFI()
pop_time = ffi.new("float*", 1024)
pop_count = ffi.new("int*", 1)

pop_click.PopsClicksDetection('E:/fs_work/fruit-salad/resources/glitch2.wav', pop_time, 1024, pop_count)


I'm using python 3.5.2 version on windows 7 machine.

Could you please help me with this issue?

Thanks,
Satya.

Daniel Holth

unread,
Dec 14, 2016, 10:22:31 AM12/14/16
to python-cffi
You should try to use cffi only. ctypes and cffi are not meant to be used together. Follow the example http://cffi.readthedocs.io/en/latest/overview.html#simple-example-abi-level-in-line, passing the full path to your DLL to the ffi.dlopen() call.

--
-- python-cffi: To unsubscribe from this group, send email to python-cffi...@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/python-cffi?hl=en
---
You received this message because you are subscribed to the Google Groups "python-cffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-cffi...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Satya Rao

unread,
Dec 15, 2016, 1:05:12 AM12/15/16
to python-cffi
Hi Daniel,

I tried with only cffi like below, but I'm getting cdef parse error.

my code:
------------

from cffi import FFI
ffi = FFI()

ffi.cdef("""
typedef enum PopRetCode;
PopRetCode PopsClicksDetection( char *filename, float *pop_time, int pop_time_size, int *pop_count );
""")

ffi.dlopen("E:/fs_work/fruit-salad/lib/fft_x86.dll")
C = ffi.dlopen("E:/fs_work/fruit-salad/lib/pops_clicks_detection.dll")


pop_time = ffi.new("float*", 1024)
pop_count = ffi.new("int*", 1)
C.PopsClicksDetection("E:/fs_work/fruit-salad/resources/glitch2.wav", pop_time, 1024, pop_count)


I am getting the following error stack trace.

E:\Frameworks\Python\Pytest\tests>python pops_clicks_detection2.py
Traceback (most recent call last):
  File "C:\Python352\lib\site-packages\cffi\cparser.py", line 260, in _parse
    ast = _get_parser().parse(csource)
  File "C:\Python352\lib\site-packages\pycparser\c_parser.py", line 151, in parse
    debug=debuglevel)
  File "C:\Python352\lib\site-packages\pycparser\ply\yacc.py", line 331, in parse
    return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
  File "C:\Python352\lib\site-packages\pycparser\ply\yacc.py", line 1181, in parseopt_notrack
    tok = call_errorfunc(self.errorfunc, errtoken, self)
  File "C:\Python352\lib\site-packages\pycparser\ply\yacc.py", line 193, in call_errorfunc
    r = errorfunc(token)
  File "C:\Python352\lib\site-packages\pycparser\c_parser.py", line 1721, in p_error
    column=self.clex.find_tok_column(p)))
  File "C:\Python352\lib\site-packages\pycparser\plyparser.py", line 55, in _parse_error
    raise ParseError("%s: %s" % (coord, msg))
pycparser.plyparser.ParseError: :4:20: before: PopsClicksDetection

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "pops_clicks_detection2.py", line 7, in <module>
    """)
  File "C:\Python352\lib\site-packages\cffi\api.py", line 105, in cdef
    self._cdef(csource, override=override, packed=packed)
  File "C:\Python352\lib\site-packages\cffi\api.py", line 119, in _cdef
    self._parser.parse(csource, override=override, **options)
  File "C:\Python352\lib\site-packages\cffi\cparser.py", line 299, in parse
    self._internal_parse(csource)
  File "C:\Python352\lib\site-packages\cffi\cparser.py", line 304, in _internal_parse
    ast, macros, csource = self._parse(csource)
  File "C:\Python352\lib\site-packages\cffi\cparser.py", line 262, in _parse
    self.convert_pycparser_error(e, csource)
  File "C:\Python352\lib\site-packages\cffi\cparser.py", line 291, in convert_pycparser_error
    raise api.CDefError(msg)
cffi.api.CDefError: cannot parse "PopRetCode PopsClicksDetection( char *filename, float *pop_time, int pop_time_size, int *pop_count );"
:4:20: before: PopsClicksDetection

E:\Frameworks\Python\Pytest\tests>

Please help me with the solution.

Satya Rao

unread,
Dec 15, 2016, 4:10:33 AM12/15/16
to python-cffi
Hi Daniel,
  I have resolved the following error, but I'm still getting one more error says "TypeError: initializer for ctype 'char *' must be a bytes or list or tuple, not str"

Here is my new python code snippet:
--------------------------------------------------------

from cffi import FFI
ffi = FFI()

ffi.cdef("""
typedef enum PopRetCode
        { FILEOPEN_ERROR = -1,
NO_POPS = 0,
POPS_DETECTED = 1,
NO_MEMORY = 2
} PopRetCode;
        PopRetCode PopsClicksDetection( char *filename, float *pop_time, int pop_time_size, int *pop_count );
""")

ffi.dlopen("E:/fs_work/fruit-salad/lib/fft_x86.dll")
C = ffi.dlopen("E:/fs_work/fruit-salad/lib/pops_clicks_detection.dll")

#file_name = ffi.new("char*", 'E:/fs_work/fruit-salad/resources/glitch2.wav')
pop_time = ffi.new("float*", 1024)
pop_count = ffi.new("int*", 1)
C.PopsClicksDetection("E:/fs_work/fruit-salad/resources/glitch2.wav", pop_time, 1024, pop_count)


And here is the error stack trace that I'm getting now with the above code.

E:\Frameworks\Python\Pytest\tests>python pops_clicks_detection2.py
Traceback (most recent call last):
  File "pops_clicks_detection2.py", line 20, in <module>
    C.PopsClicksDetection("E:/fs_work/fruit-salad/resources/glitch2.wav", pop_time, 1024, pop_count)
TypeError: initializer for ctype 'char *' must be a bytes or list or tuple, not str

E:\Frameworks\Python\Pytest\tests>

Please help with this issue.

Thanks,
Satya.

Simon Davy

unread,
Dec 15, 2016, 4:38:27 AM12/15/16
to pytho...@googlegroups.com
Hi Satya


On 15 Dec 2016 9:10 am, "Satya Rao" <sat...@gmail.com> wrote:
Hi Daniel,
  I have resolved the following error, but I'm still getting one more error says "TypeError: initializer for ctype 'char *' must be a bytes or list or tuple, not str"

Here is my new python code snippet:
--------------------------------------------------------

from cffi import FFI
ffi = FFI()

ffi.cdef("""
typedef enum PopRetCode
{ FILEOPEN_ERROR = -1,
NO_POPS = 0,
POPS_DETECTED = 1,
NO_MEMORY = 2
} PopRetCode;
PopRetCode PopsClicksDetection( char *filename, float *pop_time, int pop_time_size, int *pop_count );
""")

ffi.dlopen("E:/fs_work/fruit-salad/lib/fft_x86.dll")
C = ffi.dlopen("E:/fs_work/fruit-salad/lib/pops_clicks_detection.dll")

#file_name = ffi.new("char*", 'E:/fs_work/fruit-salad/resources/glitch2.wav')
pop_time = ffi.new("float*", 1024)
pop_count = ffi.new("int*", 1)
C.PopsClicksDetection("E:/fs_work/fruit-salad/resources/glitch2.wav", pop_time, 1024, pop_count)


Try adding a 'b' prefix to the path string, to tell python it's a byte string rather than Unicode.

I.e.

C.PopsClicksDetection(b"E:/fs_work/fruit-salad/resources/glitch2.wav", ...)


--
-- python-cffi: To unsubscribe from this group, send email to python-cffi+unsubscribe@googlegroups.com. For more options, visit this group at https://groups.google.com/d/forum/python-cffi?hl=en

---
You received this message because you are subscribed to the Google Groups "python-cffi" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-cffi+unsubscribe@googlegroups.com.

Satya Rao

unread,
Dec 15, 2016, 7:22:04 AM12/15/16
to python-cffi
Thanks Simon! Now it's working.
Thanks Daniel for your support.
Reply all
Reply to author
Forward
0 new messages