def get_cpu_info(self): """ Retrieves CPU info from client """ info = snap7.snap7types.S7CpuInfo() result = self.library.Cli_GetCpuInfo(self.pointer, byref(info)) check_error(result, context="client") return info
def list_blocks_of_type(self, blocktype, size): """This function returns the AG list of a specified block type.""" blocktype = snap7.snap7types.block_types.get(blocktype) if not blocktype: raise Snap7Exception("The blocktype parameter was invalid") logger.debug("listing blocks of type: %s size: %s" % (blocktype, size)) if (size == 0): return 0 data = (c_uint16 * size)() count = c_int(size) result = self.library.Cli_ListBlocksOfType( self.pointer, blocktype, byref(data), byref(count)) logger.debug("number of items found: %s" % count) check_error(result, context="client") return data
def get_mask(self, kind): """Reads the specified filter mask. """ logger.debug("retrieving mask kind %s" % kind) mask = longword() code = self.library.Srv_GetMask(self.pointer, kind, ctypes.byref(mask)) check_error(code) return mask
def disconnect(self): """ disconnect a client. """ logger.info("disconnecting snap7 client") result = self.library.Cli_Disconnect(self.pointer) check_error(result, context="client") return result
def get_last_error(self): """ Returns the last job result. """ error = ctypes.c_int32() result = self.library.Par_GetLastError(self.pointer, ctypes.byref(error)) check_error(result, "partner") return error
def get_status(self): """ Returns the Partner status. """ status = ctypes.c_int32() result = self.library.Par_GetStatus(self.pointer, ctypes.byref(status)) check_error(result, "partner") return status
def read(self, vm_address): """ Reads from VM addresses of Siemens Logo. Examples: read("V40") / read("VW64") / read("V10.2") :param vm_address: of Logo memory (e.g. V30.1, VW32, V24) :returns: integer """ area = snap7types.S7AreaDB db_number = 1 size = 1 start = 0 wordlen = 0 logger.debug("read, vm_address:%s" % (vm_address)) if re.match("V[0-9]{1,4}\.[0-7]{1}", vm_address): ## bit value logger.info("read, Bit address: " + vm_address) address = vm_address[1:].split(".") # transform string to int address_byte = int(address[0]) address_bit = int(address[1]) start = (address_byte*8)+address_bit wordlen = snap7types.S7WLBit elif re.match("V[0-9]+", vm_address): ## byte value logger.info("Byte address: " + vm_address) start = int(vm_address[1:]) wordlen = snap7types.S7WLByte elif re.match("VW[0-9]+", vm_address): ## byte value logger.info("Word address: " + vm_address) start = int(vm_address[2:]) wordlen = snap7types.S7WLWord elif re.match("VD[0-9]+", vm_address): ## byte value logger.info("DWord address: " + vm_address) start = int(vm_address[2:]) wordlen = snap7types.S7WLDWord else: logger.info("Unknown address format") return 0 type_ = snap7.snap7types.wordlen_to_ctypes[wordlen] data = (type_ * size)() logger.debug("start:%s, wordlen:%s, data-length:%s" % (start, wordlen, len(data)) ) result = self.library.Cli_ReadArea(self.pointer, area, db_number, start, size, wordlen, byref(data)) check_error(result, context="client") # transform result to int value if wordlen == snap7types.S7WLBit: return(data)[0] if wordlen == snap7types.S7WLByte: return struct.unpack_from(">B", data)[0] if wordlen == snap7types.S7WLWord: return struct.unpack_from(">h", data)[0] if wordlen == snap7types.S7WLDWord: return struct.unpack_from(">l", data)[0]
def db_get(self, db_number): """Uploads a DB from AG. """ logging.debug("db_get db_number: %s" % db_number) _buffer = buffer_type() result = self.library.Cli_DBGet(self.pointer, db_number, byref(_buffer), byref(c_int(buffer_size))) check_error(result, context="client") return bytearray(_buffer)
def db_get(self, db_number): """Uploads a DB from AG. """ logging.debug("db_get db_number: %s" % db_number) buffer_ = buffer_type() result = clib.Cli_DBGet(self.pointer, db_number, byref(buffer_), byref(c_int(buffer_size))) check_error(result, client=True) return bytearray(buffer_)
def get_param(self, number): """Reads an internal Server object parameter. """ logger.debug("retreiving param number %s" % number) value = ctypes.c_int() code = self.library.Srv_GetParam(self.pointer, number, ctypes.byref(value)) check_error(code) return value.value
def get_connected(self): """ Returns the connection status :returns: a boolean that indicates if connected. """ connected = c_int32() result = self.library.Cli_GetConnected(self.pointer, byref(connected)) check_error(result, context="client") return bool(connected)
def get_param(self, number): """Reads an internal Client object parameter. """ logger.debug("retreiving param number %s" % number) type_ = param_types[number] value = type_() code = self.library.Cli_GetParam(self.pointer, c_int(number), byref(value)) check_error(code) return value.value
def read_multi_vars(self, items): """This function read multiple variables from the PLC. :param items: list of S7DataItem objects :returns: a tuple with the return code and a list of data items """ result = self.library.Cli_ReadMultiVars(self.pointer, byref(items), c_int32(len(items))) check_error(result, context="client") return result, items
def get_times(self): """ Returns the last send and recv jobs execution time in milliseconds. """ send_time = ctypes.c_int32() recv_time = ctypes.c_int32() result = self.library.Par_GetTimes(self.pointer, ctypes.byref(send_time), ctypes.byref(recv_time)) check_error(result, "partner") return send_time, recv_time
def as_db_get(self, db_number): """ This is the asynchronous counterpart of Cli_DBGet. """ # logger.debug("db_get db_number: %s" % db_number) _buffer = buffer_type() bufferSize = c_int(snap7.snap7types.buffer_size) result = self.library.Cli_AsDBGet(self.pointer, db_number, byref(_buffer), byref(bufferSize)) check_error(result, context="client") msg = bytearray(_buffer[:bufferSize.value]) return msg
def get_pdu_length(self): """ Returns info about the PDU length. """ logger.info("getting PDU length") requested_ = c_uint16() negotiated_ = c_uint16() code = self.library.Cli_GetPduLength(self.pointer, byref(requested_), byref(negotiated_)) check_error(code) return negotiated_.value
def get_param(self, number): """ Reads an internal Partner object parameter. """ logger.debug("retreiving param number %s" % number) type_ = snap7.snap7types.param_types[number] value = type_() code = self.library.Par_GetParam(self.pointer, ctypes.c_int(number), ctypes.byref(value)) check_error(code) return value.value
def as_db_get(self, db_number): """ This is the asynchronous counterpart of Cli_DBGet. """ logging.debug("db_get db_number: %s" % db_number) _buffer = buffer_type() result = self.library.Cli_AsDBGet(self.pointer, db_number, byref(_buffer), byref(c_int(buffer_size))) check_error(result, context="client") return bytearray(_buffer)
def list_blocks(self): """Returns the AG blocks amount divided by type. :returns: a snap7.types.BlocksList object. """ logging.debug("listing blocks") blocksList = BlocksList() result = self.library.Cli_ListBlocks(self.pointer, byref(blocksList)) check_error(result, context="client") logging.debug("blocks: %s" % blocksList) return blocksList
def read_area(self, area, dbnumber, start, amount, wordlen): """This is the main function to read data from a PLC. With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters. """ logging.debug("reading area: %s dbnumber: %s start: %s: amount %s: " "wordlen: %s" % (area, dbnumber, start, amount, wordlen)) data = (wordlen_to_ctypes[wordlen] * amount)() result = clib.Cli_ReadArea(self.pointer, area, dbnumber, start, amount, wordlen, byref(data)) check_error(result, client=True) return data
def set_param(self, number, value): """Sets an internal Server object parameter. :param number: Parameter type number :param value: Parameter value """ logger.debug("setting param number %s to %s" % (number, value)) type_ = param_types[number] result = self.library.Cli_SetParam(self.pointer, number, byref(type_(value))) check_error(result, context="client") return result
def db_get(self, db_number): """Uploads a DB from AG. """ # logger.debug("db_get db_number: %s" % db_number) _buffer = buffer_type() bufferSize = c_int(snap7.snap7types.buffer_size) result = self.library.Cli_DBGet( self.pointer, db_number, byref(_buffer), byref(bufferSize)) check_error(result, context="client") msg = bytearray(_buffer[:bufferSize.value]) return msg
def ab_read(self, start, size): """ This is a lean function of Cli_ReadArea() to read PLC process outputs. """ wordlen = snap7.snap7types.S7WLByte type_ = snap7.snap7types.wordlen_to_ctypes[wordlen] data = (type_ * size)() logging.debug("ab_read: start: %s: size %s: " % (start, size)) result = self.library.Cli_ABRead(self.pointer, start, size, byref(data)) check_error(result, context="client") return bytearray(data)
def as_ab_read(self, start, size): """ This is the asynchronous counterpart of client.ab_read(). """ wordlen = snap7.snap7types.S7WLByte type_ = snap7.snap7types.wordlen_to_ctypes[wordlen] data = (type_ * size)() logging.debug("ab_read: start: %s: size %s: " % (start, size)) result = self.library.Cli_AsABRead(self.pointer, start, size, byref(data)) check_error(result, context="client") return bytearray(data)
def pick_event(self): """Extracts an event (if available) from the Events queue. """ logger.debug("checking event queue") event = SrvEvent() ready = ctypes.c_int32() code = self.library.Srv_PickEvent(self.pointer, ctypes.byref(event), ctypes.byref(ready)) check_error(code) if ready: logger.debug("one event ready: %s" % event) return event logger.debug("no events ready")
def as_db_read(self, db_number, start, size): """ This is the asynchronous counterpart of Cli_DBRead. :returns: user buffer. """ # logger.debug("db_read, db_number:%s, start:%s, size:%s" % (db_number, start, size)) type_ = snap7.snap7types.wordlen_to_ctypes[snap7.snap7types.S7WLByte] data = (type_ * size)() result = (self.library.Cli_AsDBRead(self.pointer, db_number, start, size, byref(data))) check_error(result, context="client") return bytearray(data)
def list_blocks_of_type(self, blocktype, size=1024): """This function returns the AG list of a specified block type.""" # logger.debug("listing blocks of type: %s size: %s" % (blocktype, size)) _buffer = (snap7.types.word * size)() count = c_int(size) result = self.library.Cli_ListBlocksOfType( self.pointer, blocktype, byref(_buffer), byref(count)) # logger.debug("number of items found: %s" % count.value) check_error(result, context="client") return _buffer[:count.value]
def list_blocks_of_type(self, blocktype, size): """This function returns the AG list of a specified block type.""" logging.debug("listing blocks of type: %s size: %s" % (blocktype, size)) data = (c_int * 10)() count = c_int(size) result = clib.Cli_ListBlocksOfType(self.pointer, blocktype, byref(data), byref(count)) logging.debug("number of items found: %s" % count) check_error(result, client=True) return data
def event_text(self, event): """Returns a textual explanation of a given event object :param event: an PSrvEvent struct object :returns: the error string """ logger.debug("error text for %s" % hex(event.EvtCode)) len_ = 1024 text_type = ctypes.c_char * len_ text = text_type() error = self.library.Srv_EventText(ctypes.byref(event), ctypes.byref(text), len_) check_error(error) return text.value
def db_read(self, db_number, start, size): """This is a lean function of Cli_ReadArea() to read PLC DB. :returns: user buffer. """ logger.debug("db_read, db_number:%s, start:%s, size:%s" % (db_number, start, size)) type_ = snap7.snap7types.wordlen_to_ctypes[snap7.snap7types.S7WLByte] data = (type_ * size)() result = (self.library.Cli_DBRead(self.pointer, db_number, start, size, byref(data))) check_error(result, context="client") return bytearray(data)
def read_area(self, area, dbnumber, start, size) -> bytearray: """This is the main function to read data from a PLC. With it you can read DB, Inputs, Outputs, Merkers, Timers and Counters. :param dbnumber: The DB number, only used when area= S7AreaDB :param start: offset to start writing :param size: number of units to read """ assert area in snap7.types.areas.values() if area == snap7.types.S7AreaTM: wordlen = snap7.types.S7WLTimer elif area == snap7.types.S7AreaCT: wordlen = snap7.types.S7WLCounter else: wordlen = snap7.types.S7WLByte type_ = snap7.types.wordlen_to_ctypes[wordlen] logger.debug( f"reading area: {area} dbnumber: {dbnumber} start: {start}: amount {size}: wordlen: {wordlen}" ) data = (type_ * size)() result = self._library.Cli_ReadArea(self._pointer, area, dbnumber, start, size, wordlen, byref(data)) check_error(result, context="client") return bytearray(data)
def f(*args, **kw): code = func(*args, **kw) check_error(code, client=True)
def f(*args, **kw): code = func(*args, **kw) check_error(code, context="client")
def s7_multi_read(plc, tag_type, tag_address, data_type, tag_name): ''' 从s7_read_excel处理完的变量表中批量读取变量 ''' taglens = len(tag_type) data_items = (S7DataItem * taglens)() # 括号 数组 # fixme 如果只有一个变量的情况 可能会有bug # 生成 data_items 待读取的变量结构体 for i in range(taglens): # print(i) data_items[i].Area = areas[tag_type[i]] # 数据类型 data_items[i].WordLen = ctypes.c_int32(S7WLByte) data_items[i].Result = ctypes.c_int32(0) data_items[i].DBNumber = ctypes.c_int32(0) # DB块 非DB写0 data_items[i].Start = ctypes.c_int32( int(tag_address[i].split('.')[0])) # byte地址 data_items[i].Amount = ctypes.c_int32(8) # 读取8位 for di in data_items: # create the buffer buffer = ctypes.create_string_buffer(di.Amount) # cast the pointer to the buffer to the required type pBuffer = ctypes.cast(ctypes.pointer(buffer), ctypes.POINTER(ctypes.c_uint8)) di.pData = pBuffer # fixme 分批读取 snap7单次20个以上报错 数组切片报错 暂时未使用 def readten(data_items): """ :type data_items: object """ # print(type(data_items)) # print(type(data_items[10:20])) # a=plc.read_multi_vars(data_items[10:20]) # print(a) l = len(data_items) # 变量表长度,如果大于20 必须分批读取 snp7 x = l // 20 # 取整 y = l % 20 # 取余数 a = 0 # 每一组变量的上标 val = [] # 初始化列表 每一组变量值 for n in range(x): if n < x: val = val + plc.read_multi_vars(data_items) a += 1 n += 1 if n == x and y != 0: val = val + plc.read_multi_vars(data_items) val2 = val return val2 result, data_items = plc.read_multi_vars(data_items) # print('读取的原始数据',data_items) ttt = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) for di in data_items: check_error(di.Result) result_values = [] # function to cast bytes to match data_types[] above # byte_to_value = [util.get_bool, util.get_real, util.get_int,util.get_dword,util.get_string] # unpack and test the result of each read # todo 做一个函数列表,合并循环。逻辑上需要先读取,后get_bool for i in range(0, len(data_items)): ddd = data_items[i] d_bit = int(tag_address[i].split('.')[1]) if data_type[i] == 'Bool': value = util.get_bool(ddd.pData, 0, d_bit) elif data_type[i] == 'Real': value = util.get_real(ddd.pData, d_bit) elif data_type[i] == 'Int': value = util.get_int(ddd.pData, d_bit) elif data_type[i] == 'Dword': value = util.get_dword(ddd.pData, d_bit) elif data_type[i] == 'String': value = util.get_string(ddd.pData, d_bit) result_values.append(value) # fixme # client.disconnect() # client.destroy() siemensdata = dict(zip(tag_name, result_values)) # print(siemensdata) return siemensdata, ttt
data_items[2].Amount = ctypes.c_int32(2) # reading an INT, 2 bytes # create buffers to receive the data # use the Amount attribute on each item to size the buffer for di in data_items: # create the buffer buffer = ctypes.create_string_buffer(di.Amount) # cast the pointer to the buffer to the required type pBuffer = ctypes.cast(ctypes.pointer(buffer), ctypes.POINTER(ctypes.c_uint8)) di.pData = pBuffer result, data_items = client.read_multi_vars(data_items) for di in data_items: check_error(di.Result) # struct formats fmts = ['>f', '>f', '>h'] # unpack and print the result of each read for i in range(0, len(data_items)): fmt = fmts[i] di = data_items[i] foo = ''.join([chr(di.pData[i]) for i in range(0, di.Amount)]) fnum = struct.unpack(fmt, foo)[0] print(fnum) client.disconnect() client.destroy()
def get_exec_time(self) -> int: # Cli_GetExecTime time = c_int32() result = self._library.Cli_GetExecTime(self._pointer, byref(time)) check_error(result) return time.value
def set_plc_system_datetime(self) -> int: # Cli_SetPlcSystemDateTime result = self._library.Cli_SetPlcSystemDateTime(self._pointer) check_error(result) return result
def db_fill(self, db_number: int, filler: int) -> int: # Cli_DBFill result = self._library.Cli_DBFill(self._pointer, db_number, filler) check_error(result) return result
def read(self, vm_address: str): """Reads from VM addresses of Siemens Logo. Examples: read("V40") / read("VW64") / read("V10.2") Args: vm_address: of Logo memory (e.g. V30.1, VW32, V24) Returns: integer """ area = types.Areas.DB db_number = 1 size = 1 start = 0 wordlen: WordLen logger.debug(f"read, vm_address:{vm_address}") if re.match(r"V[0-9]{1,4}\.[0-7]", vm_address): # bit value logger.info(f"read, Bit address: {vm_address}") address = vm_address[1:].split(".") # transform string to int address_byte = int(address[0]) address_bit = int(address[1]) start = (address_byte * 8) + address_bit wordlen = WordLen.Bit elif re.match("V[0-9]+", vm_address): # byte value logger.info(f"Byte address: {vm_address}") start = int(vm_address[1:]) wordlen = WordLen.Byte elif re.match("VW[0-9]+", vm_address): # byte value logger.info(f"Word address: {vm_address}") start = int(vm_address[2:]) wordlen = WordLen.Word elif re.match("VD[0-9]+", vm_address): # byte value logger.info(f"DWord address: {vm_address}") start = int(vm_address[2:]) wordlen = WordLen.DWord else: logger.info("Unknown address format") return 0 type_ = snap7.types.wordlen_to_ctypes[wordlen.value] data = (type_ * size)() logger.debug( f"start:{start}, wordlen:{wordlen.name}={wordlen.value}, data-length:{len(data)}" ) result = self.library.Cli_ReadArea(self.pointer, area.value, db_number, start, size, wordlen.value, byref(data)) check_error(result, context="client") # transform result to int value if wordlen == WordLen.Bit: return data[0] if wordlen == WordLen.Byte: return struct.unpack_from(">B", data)[0] if wordlen == WordLen.Word: return struct.unpack_from(">h", data)[0] if wordlen == WordLen.DWord: return struct.unpack_from(">l", data)[0]
def as_db_fill(self, db_number: int, filler) -> int: result = self._library.Cli_AsDBFill(self._pointer, db_number, filler) check_error(result, context="client") return result
def copy_ram_to_rom(self, timeout=1) -> int: # Cli_CopyRamToRom result = self._library.Cli_CopyRamToRom(self._pointer, timeout) check_error(result) return result
def as_read_szl(self, ssl_id: int, index: int, s7_szl: S7SZL, size) -> int: # Cli_AsReadSZL result = self._library.Cli_AsReadSZL(self._pointer, ssl_id, index, byref(s7_szl), byref(size)) check_error(result, context="client") return result
def as_tm_read(self, start: int, amount: int, data) -> bytearray: # Cli_ASTMRead result = self._library.Cli_AsTMRead(self._pointer, start, amount, byref(data)) check_error(result, context="client") return result
def as_copy_ram_to_rom(self, timeout: int = 1) -> int: result = self._library.Cli_AsCopyRamToRom(self._pointer, timeout) check_error(result, context="client") return result
def as_db_write(self, db_number: int, start: int, size: int, data) -> int: result = self._library.Cli_AsDBWrite(self._pointer, db_number, start, size, byref(data)) check_error(result, context="client") return result
def get_cp_info(self) -> S7CpInfo: # Cli_GetCpInfo cp_info = S7CpInfo() result = self._library.Cli_GetCpInfo(self._pointer, byref(cp_info)) check_error(result) return cp_info
def write (self, vm_address, value): """ Writes to VM addresses of Siemens Logo. Example: write("VW10", 200) or write("V10.3", 1) :param vm_address: write offset :param value: integer """ area = snap7types.S7AreaDB db_number = 1 start = 0 amount = 1 wordlen = 0 data = bytearray(0) logger.debug("write, vm_address:%s, value:%s" % (vm_address, value)) if re.match("^V[0-9]{1,4}\.[0-7]{1}$", vm_address): ## bit value logger.info("read, Bit address: " + vm_address) address = vm_address[1:].split(".") # transform string to int address_byte = int(address[0]) address_bit = int(address[1]) start = (address_byte*8)+address_bit wordlen = snap7types.S7WLBit if value > 0: data = bytearray([1]) else: data = bytearray([0]) elif re.match("^V[0-9]+$", vm_address): ## byte value logger.info("Byte address: " + vm_address) start = int(vm_address[1:]) wordlen = snap7types.S7WLByte data = bytearray(struct.pack(">B", value)) elif re.match("^VW[0-9]+$", vm_address): ## byte value logger.info("Word address: " + vm_address) start = int(vm_address[2:]) wordlen = snap7types.S7WLWord data = bytearray(struct.pack(">h", value)) elif re.match("^VD[0-9]+$", vm_address): ## byte value logger.info("DWord address: " + vm_address) start = int(vm_address[2:]) wordlen = snap7types.S7WLDWord data = bytearray(struct.pack(">l", value)) else: logger.info("write, Unknown address format: " + vm_address) return 1 if wordlen == snap7types.S7WLBit: type_ = snap7.snap7types.wordlen_to_ctypes[snap7types.S7WLByte] else: type_ = snap7.snap7types.wordlen_to_ctypes[wordlen] cdata = (type_ * amount).from_buffer_copy(data) logger.debug("write, vm_address:%s value:%s" % (vm_address, value)) result = self.library.Cli_WriteArea(self.pointer, area, db_number, start, amount, wordlen, byref(cdata)) check_error(result, context="client") return result
def write(self, vm_address: str, value: int) -> int: """Writes to VM addresses of Siemens Logo. Args: vm_address: write offset value: integer Examples: >>> write("VW10", 200) or write("V10.3", 1) """ area = types.Areas.DB db_number = 1 start = 0 amount = 1 wordlen: WordLen data = bytearray(0) logger.debug(f"write, vm_address:{vm_address}, value:{value}") if re.match(r"^V[0-9]{1,4}\.[0-7]$", vm_address): # bit value logger.info(f"read, Bit address: {vm_address}") address = vm_address[1:].split(".") # transform string to int address_byte = int(address[0]) address_bit = int(address[1]) start = (address_byte * 8) + address_bit wordlen = WordLen.Bit if value > 0: data = bytearray([1]) else: data = bytearray([0]) elif re.match("^V[0-9]+$", vm_address): # byte value logger.info(f"Byte address: {vm_address}") start = int(vm_address[1:]) wordlen = WordLen.Byte data = bytearray(struct.pack(">B", value)) elif re.match("^VW[0-9]+$", vm_address): # byte value logger.info(f"Word address: {vm_address}") start = int(vm_address[2:]) wordlen = WordLen.Word data = bytearray(struct.pack(">h", value)) elif re.match("^VD[0-9]+$", vm_address): # byte value logger.info(f"DWord address: {vm_address}") start = int(vm_address[2:]) wordlen = WordLen.DWord data = bytearray(struct.pack(">l", value)) else: logger.info(f"write, Unknown address format: {vm_address}") return 1 if wordlen == WordLen.Bit: type_ = snap7.types.wordlen_to_ctypes[WordLen.Byte.value] else: type_ = snap7.types.wordlen_to_ctypes[wordlen.value] cdata = (type_ * amount).from_buffer_copy(data) logger.debug(f"write, vm_address:{vm_address} value:{value}") result = self.library.Cli_WriteArea(self.pointer, area.value, db_number, start, amount, wordlen.value, byref(cdata)) check_error(result, context="client") return result
def set_as_callback(self, pfn_clicompletion, p_usr): # Cli_SetAsCallback result = self._library.Cli_SetAsCallback(self._pointer, pfn_clicompletion, p_usr) check_error(result, context='client') return result
def as_ct_read(self, start: int, amount: int, data) -> int: # Cli_CTRead result = self._library.Cli_AsCTRead(self._pointer, start, amount, byref(data)) check_error(result, context="client") return result
def f(*args, **kw): code = func(*args, **kw) check_error(code, context="server")
def as_mb_read(self, start: int, size: int, data) -> int: # Cli_AsMBRead result = self._library.Cli_AsMBRead(self._pointer, start, size, byref(data)) check_error(result, context="client") return result