cffi.api.CDefError: cannot parse "PlayerState clientState"

574 views
Skip to first unread message

Satya Rao

unread,
Dec 15, 2016, 9:14:27 AM12/15/16
to python-cffi
Hi,

I am very new to cffi, can you please help me on how to write my ffi.cdef.

I want to use some functions SetUp(), StartPlaybackFromFile(), StartRecordingToFile(), StopPlayback(), StopRecording(),Terminate()  from my dll "portaudio_client_x86.dll"

Here is my python code snippet using cffi:
------------------------------------------------------------

from cffi import FFI
ffi = FFI()

ffi.cdef("""
static enum PlayerState { UNINITIALIZED = 0x0,
INITIALIZED = 0x1,
PLAYBACK_READY = 0x2,
RECORD_READY = 0x4,
PLAYING = 0x8,
RECORDING = 0x10
};
static enum PlayerStatus { PA_CLIENT_SUCCESS = 0,
PA_CLIENT_UNINITIALIZED = -1,
PA_INITIALIZATION_ERROR = -2,
PA_TERMINATION_ERROR = -3,
PA_STREAM_OPEN_ERROR = -4,
PA_STREAM_CLOSE_ERROR = -5,
PA_STREAM_START_ERROR = -6,
PA_STREAM_STOP_ERROR = -7,
PA_CLIENT_FILE_ERROR = -8,
PA_SAMPLINGRATE_SUPPORT_ERROR = -9,
PA_INVALID_HOST_API_ERROR = -10,
PA_PLAYBACK_CHANNEL_COUNT_SUPPORT_ERROR = -11,
PA_RECORDING_CHANNEL_COUNT_SUPPORT_ERROR = -12
};

typedef void (*stateCallbackType)( bool on,
PlayerState clientState
);
typedef void (*errorCallbackType)( PlayerStatus clientSatus,
int libErrorCode,
const char *pLibErrorMessage
);
PlayerStatus StartPlaybackFromFile( int playbackChannelCount,
int samplingRate,
const char *pPath
);

PlayerStatus SetUp( int bufferSize,
stateCallbackType stateCallback,
errorCallbackType errorCallback
);
PlayerStatus StartRecordingToFile( int recordChannelCount,
int SamplingRate,
const char *pPath
);
PlayerStatus Terminate();
PlayerStatus StopPlayback();
PlayerStatus StopRecording();

void ErrorCallback( const PlayerStatus clientSatus,
const int libErrorCode,
const char *pLibErrorMessage
);
""")

def sateCallBack(on, state):
print "on", on, "state", state

def errorCallBack():
print "error call back"

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

ret_code = C.PortaudioClient.SetUp(2048, sateCallBack, errorCallBack)

print(ret_code)


I'm getting following error stack trace:

E:\Frameworks\Python\Pytest\tests>python port_audio_client.py
Traceback (most recent call last):
  File "port_audio_client.py", line 55, in <module>
    """)
  File "C:\Python27\lib\site-packages\cffi\api.py", line 105, in cdef
    self._cdef(csource, override=override, packed=packed)
  File "C:\Python27\lib\site-packages\cffi\api.py", line 119, in _cdef
    self._parser.parse(csource, override=override, **options)
  File "C:\Python27\lib\site-packages\cffi\cparser.py", line 299, in parse
    self._internal_parse(csource)
  File "C:\Python27\lib\site-packages\cffi\cparser.py", line 304, in _internal_parse
    ast, macros, csource = self._parse(csource)
  File "C:\Python27\lib\site-packages\cffi\cparser.py", line 262, in _parse
    self.convert_pycparser_error(e, csource)
  File "C:\Python27\lib\site-packages\cffi\cparser.py", line 291, in convert_pycparser_error
    raise api.CDefError(msg)
cffi.api.CDefError: cannot parse "PlayerState clientState"
:27:36: before: PlayerState

E:\Frameworks\Python\Pytest\tests>

By the way I'm using Python 3.5.2 version.
Could you please help me with this issue and how to write ffi.cdef() in my case and how to call the dll functions?

I'm attaching my header files for reference.


Thanks,
Satya.



portaudio_client.h
portaudio_client_api.h

Armin Rigo

unread,
Dec 15, 2016, 11:00:04 AM12/15/16
to pytho...@googlegroups.com
Hi,

On 15 December 2016 at 15:14, Satya Rao <sat...@gmail.com> wrote:
> static enum PlayerState { UNINITIALIZED = 0x0,
> INITIALIZED = 0x1,
> PLAYBACK_READY = 0x2,
> RECORD_READY = 0x4,
> PLAYING = 0x8,
> RECORDING = 0x10
> };

> cffi.api.CDefError: cannot parse "PlayerState clientState"

The error is because your code is originally C++. In C++ you can use
PlayerState as a type name after saying only "enum PlayerState { stuff
};". It works as well for "struct Foo { int x, y, z; };". In C,
however, the namespaces are separated: you can only use "enum
PlayerState" or "struct Foo" after these declaration, not
"PlayerState" or "Foo" alone.

In C, in order to use the name "Foo" alone, you must define it with
"typedef". That's why you get C code that looks like this (which is,
admittedly, a bit strange a priori):

typedef struct Foo { int x, y, z; } Foo;

The two names are often made different (but they don't need to be):

typedef struct foo_s { int x, y, z; } foo_t;

When porting from C++, the most natural choice is to use the first option:

typedef enum PlayerState { UNINITIALIZED = 0x0,
INITIALIZED = 0x1,
PLAYBACK_READY = 0x2,
RECORD_READY = 0x4,
PLAYING = 0x8,
RECORDING = 0x10
} PlayerState;


A bientôt,

Armin.

Satya Rao

unread,
Dec 16, 2016, 1:13:05 AM12/16/16
to python-cffi
Thanks Armin, I didn't get the previous error, but I'm getting other error while calling dll function.

Here is the modified python code:
--------------------------------------------------

from cffi import FFI
ffi = FFI()

ffi.cdef("""
        typedef enum PlayerState { UNINITIALIZED = 0x0,
INITIALIZED = 0x1,
PLAYBACK_READY = 0x2,
RECORD_READY = 0x4,
PLAYING = 0x8,
RECORDING = 0x10
}PlayerState;
        typedef enum PlayerStatus { PA_CLIENT_SUCCESS = 0,
                           PA_CLIENT_UNINITIALIZED = -1,
PA_INITIALIZATION_ERROR = -2,
PA_TERMINATION_ERROR = -3,
PA_STREAM_OPEN_ERROR = -4,
PA_STREAM_CLOSE_ERROR = -5,
PA_STREAM_START_ERROR = -6,
PA_STREAM_STOP_ERROR = -7,
PA_CLIENT_FILE_ERROR = -8,
PA_SAMPLINGRATE_SUPPORT_ERROR = -9,
PA_INVALID_HOST_API_ERROR = -10,
PA_PLAYBACK_CHANNEL_COUNT_SUPPORT_ERROR = -11,
PA_RECORDING_CHANNEL_COUNT_SUPPORT_ERROR = -12
                         }PlayerStatus;

typedef void (*stateCallbackType)( bool on,
PlayerState clientState
);
typedef void (*errorCallbackType)( PlayerStatus clientSatus,
int libErrorCode,
const char *pLibErrorMessage
);
PlayerStatus StartPlaybackFromFile( int playbackChannelCount,
int samplingRate,
const char *pPath
);

PlayerStatus SetUp( int bufferSize,
stateCallbackType stateCallback,
errorCallbackType errorCallback
);
PlayerStatus StartRecordingToFile( int recordChannelCount,
int SamplingRate,
const char *pPath
);
PlayerStatus Terminate();
PlayerStatus StopPlayback();
PlayerStatus StopRecording();
         void StatusCallback( const bool        on,
const PlayerState clientState
                                 );
void ErrorCallback( const PlayerStatus clientSatus,
const int libErrorCode,
const char *pLibErrorMessage
);
""")

def sateCallBack(on, state):
print "on", on, "state", state

def errorCallBack():
print "error call back"

ffi.dlopen("E:/fs_work/fruit-salad/lib/portaudio_x86.dll")
ffi.dlopen("E:/fs_work/fruit-salad/lib/libsndfile-1.dll")

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

ret_code = C.PortaudioClient.SetUp(2048, sateCallBack, errorCallBack)

print(ret_code)


And I'm getting the following error.

E:\Frameworks\Python\Pytest\tests>python port_audio_client.py
Traceback (most recent call last):
  File "port_audio_client.py", line 69, in <module>
    ret_code = C.PortaudioClient.SetUp(2048, sateCallBack, errorCallBack)
  File "C:\Python27\lib\site-packages\cffi\api.py", line 837, in __getattr__
    make_accessor(name)
  File "C:\Python27\lib\site-packages\cffi\api.py", line 832, in make_accessor
    raise AttributeError(name)
AttributeError: PortaudioClient

E:\Frameworks\Python\Pytest\tests>


I don't know how to pass call back functions (sateCallBack & errorCallBack) as arguments of my dll function when calling from cffi. 
Could you please guide me on this.

Thanks,
Satya.

Satya Rao

unread,
Dec 16, 2016, 4:10:30 AM12/16/16
to python-cffi
Hi 
I have modified my code slightly and now I'm getting the following error.

E:\Frameworks\Python\Pytest\tests>python port_audio_client.py
Traceback (most recent call last):
  File "port_audio_client.py", line 70, in <module>
    ret_code = C.SetUp(2048, sateCallBack, errorCallBack)
TypeError: initializer for ctype 'void(*)(_Bool, PlayerState)' must be a cdata pointer, not function

E:\Frameworks\Python\Pytest\tests>


Following is my updated code:
-------------------------------------------

def errorCallBack(client_status,lib_error_code,lib_error_message):
print client_status, lib_error_code, lib_error_message



ffi.dlopen("E:/fs_work/fruit-salad/lib/portaudio_x86.dll")
ffi.dlopen("E:/fs_work/fruit-salad/lib/libsndfile-1.dll")
C = ffi.dlopen("E:/fs_work/fruit-salad/lib/portaudio_client_x86.dll")

ret_code = C.SetUp(2048, sateCallBack, errorCallBack)
print(ret_code)

Please help me with this error.


Thanks,
Satya.

Satya Rao

unread,
Dec 16, 2016, 6:39:24 AM12/16/16
to python-cffi
I made it working by using cffi callback method, now it's working, no issues.
Thanks guys for all your support.

Thanks,
Satya.
Reply all
Reply to author
Forward
0 new messages