예제 #1
0
 def test_function_pointer(self):
     ffi = FFI(backend=self.Backend())
     def cb(charp):
         assert repr(charp).startswith("<cdata 'char *' 0x")
         return 42
     fptr = ffi.callback("int(*)(const char *txt)", cb)
     assert fptr != ffi.callback("int(*)(const char *)", cb)
     assert repr(fptr) == "<cdata 'int(*)(char *)' calling %r>" % (cb,)
     res = fptr(b"Hello")
     assert res == 42
     #
     if not sys.platform.startswith('linux'):
         py.test.skip("probably no symbol 'stderr' in the lib")
     ffi.cdef("""
         int fputs(const char *, void *);
         void *stderr;
     """)
     ffi.C = ffi.dlopen(None)
     fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs)
     assert fptr == ffi.C.fputs
     assert repr(fptr).startswith("<cdata 'int(*)(char *, void *)' 0x")
     with FdWriteCapture() as fd:
         fptr(b"world\n", ffi.C.stderr)
     res = fd.getvalue()
     assert res == b'world\n'
예제 #2
0
    def test_function_pointer(self):
        ffi = FFI(backend=self.Backend())

        def cb(charp):
            assert repr(charp).startswith("<cdata 'char *' 0x")
            return 42

        fptr = ffi.callback("int(*)(const char *txt)", cb)
        assert fptr != ffi.callback("int(*)(const char *)", cb)
        assert repr(fptr) == "<cdata 'int(*)(char *)' calling %r>" % (cb, )
        res = fptr(b"Hello")
        assert res == 42
        #
        if not sys.platform.startswith('linux'):
            py.test.skip("probably no symbol 'stderr' in the lib")
        ffi.cdef("""
            int fputs(const char *, void *);
            void *stderr;
        """)
        ffi.C = ffi.dlopen(None)
        fptr = ffi.cast("int(*)(const char *txt, void *)", ffi.C.fputs)
        assert fptr == ffi.C.fputs
        assert repr(fptr).startswith("<cdata 'int(*)(char *, void *)' 0x")
        with FdWriteCapture() as fd:
            fptr(b"world\n", ffi.C.stderr)
        res = fd.getvalue()
        assert res == b'world\n'
예제 #3
0
 def test_callback_returning_struct_three_bytes(self):
     if self.Backend is CTypesBackend:
         py.test.skip("not supported with the ctypes backend")
     ffi = FFI(backend=self.Backend())
     ffi.cdef("""
         typedef struct {
             unsigned char a, b, c;
         } THREEBYTES;
     """)
     def cb():
         return (12, 34, 56)
     fptr = ffi.callback("THREEBYTES(*)(void)", cb)
     tb = fptr()
     assert tb.a == 12
     assert tb.b == 34
     assert tb.c == 56
예제 #4
0
    def test_callback_returning_void(self):
        ffi = FFI(backend=self.Backend())
        for returnvalue in [None, 42]:

            def cb():
                return returnvalue

            fptr = ffi.callback("void(*)(void)", cb)
            with StdErrCapture() as f:
                returned = fptr()
            printed = f.getvalue()
            assert returned is None
            if returnvalue is None:
                assert printed == ''
            else:
                assert "None" in printed
예제 #5
0
 def test_callback_returning_void(self):
     ffi = FFI(backend=self.Backend())
     for returnvalue in [None, 42]:
         def cb():
             return returnvalue
         fptr = ffi.callback("void(*)(void)", cb)
         old_stderr = sys.stderr
         try:
             sys.stderr = StringIO()
             returned = fptr()
             printed = sys.stderr.getvalue()
         finally:
             sys.stderr = old_stderr
         assert returned is None
         if returnvalue is None:
             assert printed == ''
         else:
             assert "None" in printed
예제 #6
0
 def test_callback_returning_void(self):
     ffi = FFI(backend=self.Backend())
     for returnvalue in [None, 42]:
         def cb():
             return returnvalue
         fptr = ffi.callback("void(*)(void)", cb)
         old_stderr = sys.stderr
         try:
             sys.stderr = StringIO()
             returned = fptr()
             printed = sys.stderr.getvalue()
         finally:
             sys.stderr = old_stderr
         assert returned is None
         if returnvalue is None:
             assert printed == ''
         else:
             assert "None" in printed
예제 #7
0
 def test_callback_onerror(self):
     ffi = FFI(backend=self.Backend())
     seen = []
     def oops(*args):
         seen.append(args)
     def otherfunc():
         raise LookupError
     def cb(n):
         otherfunc()
     a = ffi.callback("int(*)(int)", cb, error=42, onerror=oops)
     res = a(234)
     assert res == 42
     assert len(seen) == 1
     exc, val, tb = seen[0]
     assert exc is LookupError
     assert isinstance(val, LookupError)
     assert tb.tb_frame.f_code.co_name == 'cb'
     assert tb.tb_frame.f_locals['n'] == 234
예제 #8
0
 def test_callback_onerror(self):
     ffi = FFI(backend=self.Backend())
     seen = []
     def oops(*args):
         seen.append(args)
     def otherfunc():
         raise LookupError
     def cb(n):
         otherfunc()
     a = ffi.callback("int(*)(int)", cb, error=42, onerror=oops)
     res = a(234)
     assert res == 42
     assert len(seen) == 1
     exc, val, tb = seen[0]
     assert exc is LookupError
     assert isinstance(val, LookupError)
     assert tb.tb_frame.f_code.co_name == 'cb'
     assert tb.tb_frame.f_locals['n'] == 234
예제 #9
0
        LEVEL_MESSAGE: 20,
        LEVEL_WARNING: 30,
        LEVEL_ERROR: 40,
        LEVEL_CRITICAL: 50,
    }


def _log_handler(domain, level, message, user_data):
    logger.log(
        GLogLevelFlags.LEVEL_TO_LOGGER[level],
        '{0}: {1}'.format(_to_string(ffi.string(domain)),
                          _to_string(ffi.string(message))))


# keep a ref to the cb to stop it being GCd
_log_handler_cb = ffi.callback('GLogFunc', _log_handler)
_log_handler_id = glib_lib.g_log_set_handler(
    _to_bytes('VIPS'), GLogLevelFlags.LEVEL_DEBUG | GLogLevelFlags.LEVEL_INFO
    | GLogLevelFlags.LEVEL_MESSAGE | GLogLevelFlags.LEVEL_WARNING
    | GLogLevelFlags.LEVEL_CRITICAL | GLogLevelFlags.LEVEL_ERROR
    | GLogLevelFlags.FLAG_FATAL | GLogLevelFlags.FLAG_RECURSION,
    _log_handler_cb, ffi.NULL)

# ffi doesn't like us looking up methods during shutdown: make a note of the
# remove handler here
_remove_handler = glib_lib.g_log_remove_handler


# we must remove the handler on exit or libvips may try to run the callback
# during shutdown
def _remove_log_handler():
예제 #10
0
def test_callback():
    ffi = FFI()
    cb = ffi.callback("int(int)", lambda x: x + 42)  # unicode literal
    assert cb(5) == 47
예제 #11
0
        r = call_no_check_errors(name, *args, **kwargs)
    finally:
        # always clear the error if the function raised something
        error, _current_error = _current_error, None

    if error:
        error, description = error
        if error in error_code_map:
            raise error_code_map[error](name, description)
        else:
            raise UnknownError(error, name, description)

    return r


# TODO consider requiring manual initialisation or initialising somewhere else?

def _on_error(error, description):
    global _current_error
    if not _current_error:
        _current_error = (error, description)


call_no_check_errors("glfwSetErrorCallback",
                     ffi.callback('GLFWerrorfun', _on_error))

if not call('glfwInit'):
    raise Exception()

atexit.register(partial(call, 'glfwTerminate'))
예제 #12
0
# All watcher subclasses must be declared above. Now we do some
# initialization; this is not only a minor optimization, it protects
# against later runtime typos and attribute errors
watcher._init_subclasses()


def _syserr_cb(msg):
    try:
        msg = ffi.string(msg)
        __SYSERR_CALLBACK(msg, ffi.errno)
    except:
        set_syserr_cb(None)
        raise  # let cffi print the traceback


_syserr_cb._cb = ffi.callback("void(*)(char *msg)", _syserr_cb)


def set_syserr_cb(callback):
    global __SYSERR_CALLBACK
    if callback is None:
        libev.ev_set_syserr_cb(ffi.NULL)
        __SYSERR_CALLBACK = None
    elif callable(callback):
        libev.ev_set_syserr_cb(_syserr_cb._cb)
        __SYSERR_CALLBACK = callback
    else:
        raise TypeError('Expected callable or None, got %r' % (callback, ))


__SYSERR_CALLBACK = None
예제 #13
0
print("moo")
from cffi import FFI

ffi = FFI()

ffi.cdef("""void (*pydo)(void); \n """)


def pydo():
    print("erm")


thing = ffi.verify("""void (*pydo)(void);""")

cb = ffi.callback("void()", pydo)
thing.pydo = cb

print("oooooo")
예제 #14
0
class LibGraphqlParser:
    def __init__(self):
        self._ffi = FFI()
        self._ffi.cdef(CDEFS_LIBGRAPHQL)
        # TODO do a conf of this ?
        try:
            self._lib = self._ffi.dlopen("/usr/local/lib/libgraphqlparser.so")
        except OSError:
            self._lib = self._ffi.dlopen("/usr/local/lib/libgraphqlparser.dylib")
        self._lib_callbacks = self._ffi.new(
            "struct GraphQLAstVisitorCallbacks *"
        )
        self._errors = self._ffi.new("char **")
        self._callbacks = []
        self._interested_by = {}
        self._default_visitor_cls = Visitor
        self._creates_callbacks()

    def _create_visitor_element(self, libgraphql_type, element):
        try:
            return _LIBGRAPHQL_TYPE_TO_CLASS[libgraphql_type](
                self._lib, self._ffi, element)
        except KeyError:
            pass

        return _VisitorElement(self._lib, self._ffi, libgraphql_type, element)

    def _callback_enter(self, libgraphql_type, element, udata):
        context = self._ffi.from_handle(udata)
        context.update(
            Visitor.IN, self._create_visitor_element(libgraphql_type, element)
        )
        return context.continue_child

    def _callback_exit(self, libgraphql_type, element, udata):
        context = self._ffi.from_handle(udata)
        if context.continue_child:
            context.update(
                Visitor.OUT, self._create_visitor_element(libgraphql_type, element)
            )
        return None

    def _set_callback(self, proto, func, attr):
        c_func = self._ffi.callback(proto)(func)
        # Keep the callbacks alive in this list
        # to keep the underlying cdata alive.
        # because we do it with reflexion and
        # not with decoration
        self._callbacks.append(c_func)
        setattr(self._lib_callbacks, attr, c_func)

    def _set_exit_callback(self, typee):
        self._set_callback(
            "void(struct GraphQLAst%s *, void *)" % typee[0],
            partial(self._callback_exit, typee[0]), "end_visit_%s" % typee[1]
        )

    def _set_enter_callback(self, typee):
        self._set_callback(
            "int(struct GraphQLAst%s *, void *)" % typee[0],
            partial(self._callback_enter, typee[0]), "visit_%s" % typee[1]
        )

    def _creates_callbacks(self):
        for typee in TYPES_LIBGRAPHQL:
            if typee[0] not in ["Name"]:
                self._set_enter_callback(typee)
                self._set_exit_callback(typee)

    def _parse(self, query):
        if isinstance(query, str):
            # TODO don't replace here.
            query = query.replace("\n", " ").encode("UTF-8")

        c_query = self._ffi.new("char[]", query)
        parsed_data = _ParsedData(
            self._lib.graphql_parse_string(c_query, self._errors),
            self._lib.graphql_node_free
        )

        if self._errors[0] != self._ffi.NULL:
            # TODO specialize Exception here
            e = Exception(
                self._ffi.string(self._errors[0]).decode('UTF-8', 'replace')
            )
            self._lib.graphql_error_free(self._errors[0])
            raise e

        return parsed_data

    def parse_and_visit(self, query, ctx=None):
        if not ctx:
            ctx = self._default_visitor_cls()

        with self._parse(query) as parsed:
            self._lib.graphql_node_visit(
                parsed, self._lib_callbacks, self._ffi.new_handle(ctx)
            )

    def parse_and_jsonify(self, query):
        with self._parse(query) as parsed:
            return self._ffi.string(self._lib.graphql_ast_to_json(parsed))
예제 #15
0
def test_callback():
    ffi = FFI()
    cb = ffi.callback("int(int)",                 # unicode literal
                      lambda x: x + 42)
    assert cb(5) == 47
예제 #16
0
print("moo")
from cffi import FFI
ffi = FFI()

ffi.cdef("""void (*pydo)(void); \n """)

def pydo():
    print("erm")

thing = ffi.verify("""void (*pydo)(void);""")

cb = ffi.callback("void()", pydo)
thing.pydo = cb

print("oooooo")
예제 #17
0
class DTrace:

    ## /usr/src/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
    DTRACE_PROBESPEC_NONE = -1
    DTRACE_PROBESPEC_PROVIDER = 0
    DTRACE_PROBESPEC_MOD = 1
    DTRACE_PROBESPEC_FUNC = 2
    DTRACE_PROBESPEC_NAME = 3

    def __init__(self):
        self._DTRACE_VERSION = 3
        self._ffi = FFI()
        self._C = self._ffi.dlopen(None)
        # print "X"*10, self._C.stdout
        self._dtrace = get_dtrace(self._ffi)
        self._dtp = None
        self._fd = None

    def get_error(self):
        if self._dtp:
            err_no = self._dtrace.dtrace_errno(self._dtp)
            err_msg_c = self._dtrace.dtrace_errmsg(self._dtp, err_no)
            err_msg = self._ffi.string(err_msg_c).decode("utf8")
            return err_no, err_msg
        else:
            return 0, None

    def open(self):
        error = self._ffi.new("int*")
        self._dtp = self._dtrace.dtrace_open(self._DTRACE_VERSION, 0, error)
        if self._dtp == self._ffi.NULL:
            err_msg_c = self._dtrace.dtrace_errmsg(self._dtp, error)
            err_msg = self._ffi.string(err_msg_c).decode("utf8")
            raise Exception(err_msg)

    def set_option(self, key, value):
        if self._dtp:
            res = self._dtrace.dtrace_setopt(self._dtp, key.encode("utf8"), value.encode("utf8"))
            if res == -1:
                err_no, err_msg = self.get_error()
                raise Exception("could not set DTrace option '{}' to '{}' - {}".format(key, value, err_msg))

    def compile(self, program):
        prog = self._dtrace.dtrace_program_strcompile(
            self._dtp, program.encode("utf8"), self._dtrace.DTRACE_PROBESPEC_NAME, 0, 0, self._ffi.NULL
        )
        if prog == self._ffi.NULL:
            err_no, err_msg = self.get_error()
            raise Exception("could not compile D program - {}".format(err_msg))

        return DTraceProgram(self, prog)

    def go(self, fd=None):
        if self._dtp:

            fd = fd or sys.stdout
            self._fd = self._ffi.cast("FILE*", fd)

            self._chew = self._ffi.callback(
                "int (const dtrace_probedata_t*, const dtrace_recdesc_t*, void*)", self.chew
            )

            res = self._dtrace.dtrace_go(self._dtp)
            if res != 0:
                err_no, err_msg = self.get_error()
                raise Exception("could not start instrumentation: {}".format(e))
            else:
                print ("instrumentation started")

    def work(self):
        if self._dtp:
            res = self._dtrace.dtrace_work(self._dtp, self._fd, self._ffi.NULL, self._chew, self._ffi.NULL)
            print ("work result: {}".format(res))

    def sleep(self):
        if self._dtp:
            res = self._dtrace.dtrace_sleep(self._dtp)
            print ("woke up")

    def stop(self):
        if self._dtp:
            res = self._dtrace.dtrace_stop(self._dtp)
            if res == -1:
                err_no, err_msg = self.get_error()
                raise Exception("could not stop instrumentation: {}".format(err_msg))
            else:
                print ("instrumentation stopped")

    def close(self):
        if self._dtp:
            self._dtrace.dtrace_close(self._dtp)
            self._dtp = None

    def chew(self, data, rec, arg):
        print ("chew!", data, rec, arg)

        # A NULL rec indicates that we've processed the last record.
        if rec == self._ffi.NULL:
            return self._dtrace.DTRACE_CONSUME_NEXT

        return self._dtrace.DTRACE_CONSUME_THIS
예제 #18
0
if __name__ == '__main__':

    ctx = ffi.new("struct sr_context **")

    def callback_imp(sdi, packet, private_data):
        global count
        count += 1
        if packet.type == sigrok.SR_DF_LOGIC:
            data = ffi.cast("struct sr_datafeed_logic*", packet.payload)

            print(data.length, data.unitsize)
            buf = ffi.buffer(data.data, data.length)
            for read in map(bin, map(ord, buf[:])):
                print(read)
    callback = ffi.callback("sr_datafeed_callback_t", callback_imp)


    assert sigrok.sr_init(ctx) == sigrok.SR_OK
    try:
        dlist = sigrok.sr_driver_list()
        i = 0
        while True:
            driver = dlist[i]
            i += 1
            if driver == ffi.NULL:
                break
            assert sigrok.sr_driver_init(ctx[0], driver) == sigrok.SR_OK
            res = sigrok.sr_driver_scan(driver, ffi.NULL)
            if res != ffi.NULL:
                name = ffi.string(driver[0].name)
예제 #19
0
    def test_types(tp_args, tp_result):
        global TEST_RUN_COUNTER
        print(tp_args, tp_result)
        cdefs = []
        structs = {}

        def build_type(tp):
            if type(tp) is list:
                field_types = [build_type(tp1) for tp1 in tp]
                fields = ['%s f%d;' % (ftp, j)
                          for (j, ftp) in enumerate(field_types)]
                fields = '\n    '.join(fields)
                name = 's%d' % len(cdefs)
                cdefs.append("typedef struct {\n    %s\n} %s;" % (fields, name))
                structs[name] = field_types
                return name
            else:
                return tp

        args = [build_type(tp) for tp in tp_args]
        result = build_type(tp_result)

        TEST_RUN_COUNTER += 1
        signature = "%s testfargs(%s)" % (result,
            ', '.join(['%s a%d' % (arg, i) for (i, arg) in enumerate(args)])
            or 'void')

        source = list(cdefs)

        cdefs.append("%s;" % signature)
        cdefs.append("extern %s testfargs_result;" % result)
        for i, arg in enumerate(args):
            cdefs.append("extern %s testfargs_arg%d;" % (arg, i))
        source.append("%s testfargs_result;" % result)
        for i, arg in enumerate(args):
            source.append("%s testfargs_arg%d;" % (arg, i))
        source.append(signature)
        source.append("{")
        for i, arg in enumerate(args):
            source.append("    testfargs_arg%d = a%d;" % (i, i))
        source.append("    return testfargs_result;")
        source.append("}")

        typedef_line = "typedef %s;" % (signature.replace('testfargs',
                                                          '(*mycallback_t)'),)
        assert signature.endswith(')')
        sig_callback = "%s testfcallback(mycallback_t callback)" % result
        cdefs.append(typedef_line)
        cdefs.append("%s;" % sig_callback)
        source.append(typedef_line)
        source.append(sig_callback)
        source.append("{")
        source.append("    return callback(%s);" %
                ', '.join(["testfargs_arg%d" % i for i in range(len(args))]))
        source.append("}")

        ffi = FFI()
        ffi.cdef("\n".join(cdefs))
        lib = verify(ffi, 'test_function_args_%d' % TEST_RUN_COUNTER,
                     "\n".join(source), no_cpp=True)

        # when getting segfaults, enable this:
        if False:
            from extra_tests.cffi_tests.udir import udir
            import subprocess
            f = open(str(udir.join('run1.py')), 'w')
            f.write('import sys; sys.path = %r\n' % (sys.path,))
            f.write('from _CFFI_test_function_args_%d import ffi, lib\n' %
                    TEST_RUN_COUNTER)
            for i in range(len(args)):
                f.write('a%d = ffi.new("%s *")\n' % (i, args[i]))
            aliststr = ', '.join(['a%d[0]' % i for i in range(len(args))])
            f.write('lib.testfargs(%s)\n' % aliststr)
            f.write('ffi.addressof(lib, "testfargs")(%s)\n' % aliststr)
            f.close()
            print("checking for segfault for direct call...")
            rc = subprocess.call([sys.executable, 'run1.py'], cwd=str(udir))
            assert rc == 0, rc

        def make_arg(tp):
            if tp in structs:
                return [make_arg(tp1) for tp1 in structs[tp]]
            else:
                return draw_primitive(ffi, tp)

        passed_args = [make_arg(arg) for arg in args]
        returned_value = make_arg(result)

        def write(p, v):
            if type(v) is list:
                for i, v1 in enumerate(v):
                    write(ffi.addressof(p, 'f%d' % i), v1)
            else:
                p[0] = v

        write(ffi.addressof(lib, 'testfargs_result'), returned_value)

        ## CALL forcing libffi
        print("CALL forcing libffi")
        received_return = ffi.addressof(lib, 'testfargs')(*passed_args)
        ##

        _tp_long_double = ffi.typeof("long double")
        def check(p, v):
            if type(v) is list:
                for i, v1 in enumerate(v):
                    check(ffi.addressof(p, 'f%d' % i), v1)
            else:
                if ffi.typeof(p).item is _tp_long_double:
                    assert ffi.cast("double", p[0]) == v
                else:
                    assert p[0] == v

        for i, arg in enumerate(passed_args):
            check(ffi.addressof(lib, 'testfargs_arg%d' % i), arg)
        ret = ffi.new(result + "*", received_return)
        check(ret, returned_value)

        ## CALLBACK
        def expand(value):
            if isinstance(value, ffi.CData):
                t = ffi.typeof(value)
                if t is _tp_long_double:
                    return float(ffi.cast("double", value))
                return [expand(getattr(value, 'f%d' % i))
                        for i in range(len(t.fields))]
            else:
                return value

        # when getting segfaults, enable this:
        if False:
            from extra_tests.cffi_tests.udir import udir
            import subprocess
            f = open(str(udir.join('run1.py')), 'w')
            f.write('import sys; sys.path = %r\n' % (sys.path,))
            f.write('from _CFFI_test_function_args_%d import ffi, lib\n' %
                    TEST_RUN_COUNTER)
            f.write('def callback(*args): return ffi.new("%s *")[0]\n' % result)
            f.write('fptr = ffi.callback("%s(%s)", callback)\n' % (result,
                                                                ','.join(args)))
            f.write('print(lib.testfcallback(fptr))\n')
            f.close()
            print("checking for segfault for callback...")
            rc = subprocess.call([sys.executable, 'run1.py'], cwd=str(udir))
            assert rc == 0, rc

        seen_args = []
        def callback(*args):
            seen_args.append([expand(arg) for arg in args])
            return returned_value

        fptr = ffi.callback("%s(%s)" % (result, ','.join(args)), callback)
        print("CALL with callback")
        received_return = lib.testfcallback(fptr)

        assert len(seen_args) == 1
        assert passed_args == seen_args[0]
        ret = ffi.new(result + "*", received_return)
        check(ret, returned_value)