def _gen_c(cls): """Creates the wl_interface C struct Generates the CFFI cdata for the wl_interface struct given by the interface. """ # Initialize the interface cdata cls._ptr.name = name = ffi.new('char[]', cls.name.encode()) cls._ptr.version = cls.version # Determine the number of methods to assign and assign them cls._ptr.method_count = len(cls.requests) cls._ptr.methods = methods_ptr = ffi.new("struct wl_message[]", len(cls.requests)) # Iterate over the methods for i, message in enumerate(cls.requests): # First, generate the wl_message cdata msg_buf = ffi.buffer(message._ptr) methods_buf = ffi.buffer(methods_ptr + i) # Copy the contents of the cdata into the allocated cdata methods_buf[:] = msg_buf cls._ptr.event_count = len(cls.events) cls._ptr.events = events_ptr = ffi.new("struct wl_message[]", len(cls.events)) # Iterate over the methods for i, message in enumerate(cls.events): # First, generate the wl_message cdata msg_buf = ffi.buffer(message._ptr) events_buf = ffi.buffer(events_ptr + i) # Copy the contents of the cdata into the allocated cdata events_buf[:] = msg_buf weakkeydict[cls._ptr] = (name, methods_ptr, events_ptr)
def c_to_arguments(self, args_ptr): """Create a list of arguments Generate the arguments of the method from a CFFI cdata array of `wl_argument` structs that correspond to the arguments of the method as specified by the method signature. :param args_ptr: Input arguments :type args_ptr: cdata `union wl_argument []` :returns: list of args """ args = [] for i, argument in enumerate(self.arguments): arg_ptr = args_ptr[i] # Match numbers (int, unsigned, float, file descriptor) if argument.argument_type == ArgumentType.Int: args.append(arg_ptr.i) elif argument.argument_type == ArgumentType.Uint: args.append(arg_ptr.u) elif argument.argument_type == ArgumentType.Fixed: f = lib.wl_fixed_to_double(arg_ptr.f) args.append(f) elif argument.argument_type == ArgumentType.FileDescriptor: args.append(arg_ptr.h) elif argument.argument_type == ArgumentType.String: if arg_ptr == ffi.NULL: if not argument.nullable: raise Exception args.append(None) else: args.append(ffi.string(arg_ptr.s).decode()) elif argument.argument_type == ArgumentType.Object: if arg_ptr.o == ffi.NULL: if not argument.nullable: message = "Got null object parsing arguments for '{}' message, may already be destroyed".format( self.name) raise RuntimeError(message) args.append(None) else: iface = self.types[i] proxy_ptr = ffi.cast('struct wl_proxy *', arg_ptr.o) obj = iface.proxy_class.registry.get(proxy_ptr) if obj is None: raise RuntimeError( "Unable to get object for {}, was it garbage collected?" .format(proxy_ptr)) args.append(obj) elif argument.argument_type == ArgumentType.NewId: # TODO raise NotImplementedError elif argument.argument_type == ArgumentType.Array: array_ptr = arg_ptr.a args.append(ffi.buffer(array_ptr.data, array_ptr.size)[:]) else: raise Exception(f"Bad argument: {argument}") return args
def arguments_to_c(self, *args): """Create an array of `wl_argument` C structs Generate the CFFI cdata array of `wl_argument` structs that correspond to the arguments of the method as specified by the method signature. :param args: Input arguments :type args: `list` :returns: cdata `union wl_argument []` of args """ nargs = len(list(self._marshaled_arguments)) args_ptr = ffi.new('union wl_argument []', nargs) arg_iter = iter(args) refs = [] for i, argument in enumerate(self._marshaled_arguments): # New id (set to null for now, will be assigned on marshal) # Then, continue so we don't consume an arg if argument.argument_type == ArgumentType.NewId: args_ptr[i].o = ffi.NULL continue arg = next(arg_iter) # Match numbers (int, unsigned, float, file descriptor) if argument.argument_type == ArgumentType.Int: args_ptr[i].i = arg elif argument.argument_type == ArgumentType.Uint: args_ptr[i].u = arg elif argument.argument_type == ArgumentType.Fixed: if isinstance(arg, int): f = lib.wl_fixed_from_int(arg) else: f = lib.wl_fixed_from_double(arg) args_ptr[i].f = f elif argument.argument_type == ArgumentType.FileDescriptor: args_ptr[i].h = arg elif argument.argument_type == ArgumentType.String: if arg is None: if not argument.nullable: raise Exception new_arg = ffi.NULL else: new_arg = ffi.new('char []', arg.encode()) refs.append(new_arg) args_ptr[i].s = new_arg elif argument.argument_type == ArgumentType.Object: if arg is None: if not argument.nullable: raise Exception new_arg = ffi.NULL else: new_arg = ffi.cast('struct wl_object *', arg._ptr) refs.append(new_arg) args_ptr[i].o = new_arg elif argument.argument_type == ArgumentType.Array: # TODO: this is a bit messy, we probably don't want to put everything in one buffer like this new_arg = ffi.new('struct wl_array *') new_data = ffi.new('void []', len(arg)) new_arg.alloc = new_arg.size = len(arg) ffi.buffer(new_data)[:] = arg refs.append(new_arg) refs.append(new_data) if len(refs) > 0: weakkeydict[args_ptr] = tuple(refs) return args_ptr
def arguments_to_c(self, *args): """Create an array of `wl_argument` C structs Generate the CFFI cdata array of `wl_argument` structs that correspond to the arguments of the method as specified by the method signature. :param args: Input arguments :type args: `list` :returns: cdata `union wl_argument []` of args """ nargs = len(re_arg.findall(self.signature)) args_ptr = ffi.new('union wl_argument []', nargs) arg_iter = iter(args) refs = [] for i, sig_match in enumerate(re_arg.finditer(self.signature)): null, sig = sig_match.groups() # New id (set to null for now, will be assigned on marshal) # Then, continue so we don't consume an arg if sig == 'n': args_ptr[i].o = ffi.NULL continue arg = next(arg_iter) # Match numbers (int, unsigned, float, file descriptor) if sig == 'i': args_ptr[i].i = arg elif sig == 'u': args_ptr[i].u = arg elif sig == 'f': if isinstance(arg, int): f = lib.wl_fixed_from_int(arg) else: f = lib.wl_fixed_from_double(arg) args_ptr[i].f = f elif sig == 'h': args_ptr[i].h = arg # Match string elif sig == 's': if arg is None: if not null: raise Exception new_arg = ffi.NULL else: new_arg = ffi.new('char []', arg.encode()) refs.append(new_arg) args_ptr[i].s = new_arg # Object elif sig == 'o': if arg is None: if not null: raise Exception new_arg = ffi.NULL else: new_arg = ffi.cast('struct wl_object *', arg._ptr) refs.append(new_arg) args_ptr[i].o = new_arg # Array (i.e. buffer of bytes) elif sig == 'a': new_arg = ffi.new('struct wl_array *') new_data = ffi.new('void []', len(arg)) new_arg.alloc = new_arg.size = len(arg) ffi.buffer(new_data)[:] = arg refs.append(new_arg) refs.append(new_data) if refs: weakkeydict[args_ptr] = refs return args_ptr