1

I'm creating a cython wrapper around the lirc library. I've had to wrap up the lirc_config struct as described by the tutorial but I need to pass a struct lirc_config * to a function in the library.

So, the struct in question is (from /usr/include/lirc/lirc_client.h):

struct lirc_config {
    char *current_mode;
    struct lirc_config_entry *next;
    struct lirc_config_entry *first;

    int sockfd;
};

and the function I need to call is:

int lirc_code2char(struct lirc_config *config, char *code, char **string);

Here is my cython wrapper around struct lirc_config:

cdef class LircConfig:

    cdef lirc_client.lirc_config * _c_lirc_config

    def __cinit__(self, config_file):
        lirc_client.lirc_readconfig(config_file, &self._c_lirc_config, NULL)
        if self._c_lirc_config is NULL:
            raise MemoryError()

    def __dealloc__(self):
        if self._c_lirc_config is not NULL:
            lirc_client.lirc_freeconfig(self._c_lirc_config)

and the problematic line:

config = LircConfig(configname)
lirc_client.lirc_code2char(config, code, &character)

config needs to be a pointer to the struct. This:

lirc_client.lirc_code2char(&config, code, &character)

gives me the error:

cylirc.pyx:76:39: Cannot take address of Python variable

which makes sense because the & is trying to access the address of LircConfig.

This:

lirc_client.lirc_code2char(config._c_lirc_config, code, &character)

gives me the error:

cylirc.pyx:76:45: Cannot convert Python object to 'lirc_config *'

Hm, I thought I defined config._c_lirc_config as cdef lirc_client.lirc_config *. I can't seem to access the value of the struct lirc_config *.

I've tried casting and also adding the public tag to _c_lirc_config (as mentioned at the bottom of the Extension types document).

I have no idea how to call the lirc_code2char function, because cython won't let me access the struct lirc_config pointer. Any Cython experts out there?

tompreston
  • 630
  • 7
  • 24
  • I fixed it by moving the lirc_code2char function inside the LircConfig class, but now it segfaults. :/ – tompreston May 27 '13 at 23:00
  • From what you gave, I don't really see why `lirc_client.lirc_code2char(config._c_lirc_config, code, &character)` wouldn't work. Could you post the entire `.pyx`, if it is not too long ? And possibly a full use case ? – Gauthier Boaglio May 28 '13 at 02:03

1 Answers1

0

I have been able to compile the following without any problem :

#lirc_client.pyx

cdef extern from "lirc/lirc_client.h":
    struct lirc_config:
        pass

    int lirc_readconfig(char *file, lirc_config **config, char *s)
    void lirc_freeconfig(lirc_config *config)

    int lirc_nextcode(char **code)
    int lirc_code2char(lirc_config *config, char *code, char **string)

cdef class LircConfig:

    cdef lirc_config * _c_lirc_config

    def __cinit__(self, config_file):
        lirc_readconfig(config_file, &self._c_lirc_config, NULL)
        if self._c_lirc_config is NULL:
            raise MemoryError()

    def __dealloc__(self):
        if self._c_lirc_config is not NULL:
            lirc_freeconfig(self._c_lirc_config)

    def some_code2char(self, configname):
        cdef char * character
        cdef char * code
        if (lirc_nextcode(&code) == O):
            config = LircConfig(configname)
            lirc_code2char(config._c_lirc_config, code, &character)

This works too :

def some_code2char(self):
    cdef char * character
    cdef char * code
    if (lirc_nextcode(&code) == O):
        #config = LircConfig(configname)
        lirc_code2char(self._c_lirc_config, code, &character)

Note : No use of a .pyd

If this segfaults, it is more a matter of usage of the original library, than a Cython issue, I think...

Hope this helps, if not keep me in touch...

Gauthier Boaglio
  • 10,054
  • 5
  • 48
  • 85