Converting arrarys in Python to arrays in C

S

Simon Foster

I have some code which attempts to convert Python arrays (tuples of
tuples of tuples...) etc. into C arrays with equivalent contents.

The prototype code is shown below.

My only question is, is there some way of doing this without repeating
the try..except blocks ad-infinitum to handle 3D, 4D arrays etc.

I can see there is a pattern here but I can't seem to turn it into a
loop. Would a recursive solution do the trick?


cdata0 = 0

cdata1 = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 )

cdata2 = (( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ))

if __name__ == '__main__':

import sys
sys.stdout = file( 'cdata.log', 'w' )

def arrayLine( s ):
return ', '.join( [ '0x%04X' % t for t in s ] )

def array0D( data ):
print 'unsigned char = 0x%04X;' % data

def array1D( data ):
print 'unsigned char[] = { %s };' % arrayLine( data )

def array2D( data ):
array = [ 'unsigned char[][] = {' ]
for i in data:
array.append( '\t{ %s },' % arrayLine( i ))
array.append( '};' )
print '\n'.join( array )

for cdata in cdata0, cdata1, cdata2:
declare = []
try:
iter(cdata)
try:
iter(cdata[0])
try:
iter(cdata[0][0])
except TypeError:
array2D( cdata )
except TypeError:
array1D( cdata )
except TypeError:
array0D( cdata )
 
A

Anton Vredegoor

Simon Foster said:
I have some code which attempts to convert Python arrays (tuples of
tuples of tuples...) etc. into C arrays with equivalent contents.

The prototype code is shown below.

My only question is, is there some way of doing this without repeating
the try..except blocks ad-infinitum to handle 3D, 4D arrays etc.

I can see there is a pattern here but I can't seem to turn it into a
loop. Would a recursive solution do the trick?

Probably yes, but why reinvent the wheel? Numeric does what you want
already and allows for efficient conversions too [1].

Anton


[1] For example, using your code as a basis:

import Numeric

def test():
cdata0 = 0

cdata1 = ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 )

cdata2 = (( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ),
( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ))

for cdata in cdata0, cdata1, cdata2:
a = Numeric.array(cdata)
print a.shape
print a
print

if __name__=='__main__':
test()
 
F

Francis Avila

Simon Foster wrote in message
I have some code which attempts to convert Python arrays (tuples of
tuples of tuples...) etc. into C arrays with equivalent contents.

The prototype code is shown below.

This doesn't generate legal C.

It also does no bounds checking, so you may end up with a Python int that
doesn't fit into a C char. (Which is most certainly 1 byte, so why do you
use 4 hex digits to represent it?)
My only question is, is there some way of doing this without repeating
the try..except blocks ad-infinitum to handle 3D, 4D arrays etc.

Of course. This approach you used is in fact very unusual, especially with
the print statements. You've simply made a special purpose function for
each depth of array.
I can see there is a pattern here but I can't seem to turn it into a
loop. Would a recursive solution do the trick?

The recursive solution is more natural here, I think, but iterative is
possible, too.

The pattern is ', '.join(<elements>), where <elements> is {<arrayORint>}.
The rest is just fluff.

You seem to have gotten hung up on the type declaration. You can't declare
the type until you know the depth of the array, so generate the array first,
*then* get construct the declaration.

Now for homework, convert the hackish solution below into a recursive
generator. ;)

def seqtobrace(seq, depth=0):
"""Return a comma- and brace-delimited version of seq, and the depth of
seq."""
depth += 1
if isinstance(seq[0], (tuple, list)):
subelem, depths = zip(*[seqtobrace(s, depth) for s in seq])
delim = ',\n' + ' '*2*depth
depth = depths[0]
elements = delim.join(subelem)
elif isinstance(seq[0], (int, long)):
elements = ', '.join(map(hex, seq))
else:
raise TypeError, "seq must be list or tuple with int or long
leaves."
return '{ %s }' % elements, depth

def toCarray(seq, name):
"""Return an unsigned char C array declaration of name from seq."""
assert isinstance(name, basestring)
if isinstance(seq, (int, long)):
return 'unsigned char %s = 0x%X;' % (name, seq)
else:
array, depth = seqtobrace(seq)
ad = '[]'*depth
typedec = 'unsigned char%s %s = \n' % (ad, name)
return typedec + array + ';'
 
L

Lonnie Princehouse

It doesn't look to me like Numeric does what you want to do;
it looks more like you want to print out C code that initializes
a big array.

Try writing a function that counts the number of dimensions
you're working with:

import types

# quick and dirty, assumes you've only got tuples and integers
def dimensions(obj):
if not isinstance(obj, types.TupleType):
return 0
else:
return 1 + dimensions(obj[0])


# Now you don't need array0D, array1D, etc..

def write_array(data):
dims = dimensions(data)
print "unsigned char%s = " % "[]" * dims
...

I've gotta run (no time to finish this post), but hopefully that helps...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top