I have a string of 20 bytes, and I would like to convert it a ctypes.c_ubyte array for bit field manipulation purposes.
import ctypes
str_bytes = '01234567890123456789'
byte_arr = bytearray(str_bytes)
raw_bytes = (ctypes.c_ubyte*20)(*(byte_arr))
Is there a way to avoid a deep copy from str to bytearray for the sake of the cast?
Alternatively, is it possible to convert a string to a bytearray without a deep copy? (With techniques like memoryview?)
I am using Python 2.7.
Performance results:
Using eryksun and Brian Larsen's suggestion, here are the benchmarks under a vbox VM with Ubuntu 12.04 and Python 2.7.
- method1 uses my original post
- method2 uses ctype from_buffer_copy
- method3 uses ctype cast/POINTER
- method4 uses numpy
Results:
- method1 takes 3.87sec
- method2 takes 0.42sec
- method3 takes 1.44sec
- method4 takes 8.79sec
Code:
import ctypes
import time
import numpy
str_bytes = '01234567890123456789'
def method1():
result = ''
t0 = time.clock()
for x in xrange(0,1000000):
byte_arr = bytearray(str_bytes)
result = (ctypes.c_ubyte*20)(*(byte_arr))
t1 = time.clock()
print(t1-t0)
return result
def method2():
result = ''
t0 = time.clock()
for x in xrange(0,1000000):
result = (ctypes.c_ubyte * 20).from_buffer_copy(str_bytes)
t1 = time.clock()
print(t1-t0)
return result
def method3():
result = ''
t0 = time.clock()
for x in xrange(0,1000000):
result = ctypes.cast(str_bytes, ctypes.POINTER(ctypes.c_ubyte * 20))[0]
t1 = time.clock()
print(t1-t0)
return result
def method4():
result = ''
t0 = time.clock()
for x in xrange(0,1000000):
arr = numpy.asarray(str_bytes)
result = arr.ctypes.data_as(ctypes.POINTER(ctypes.c_ubyte*len(str_bytes)))
t1 = time.clock()
print(t1-t0)
return result
print(method1())
print(method2())
print(method3())
print(method4())