A similar code snippet in Python might be:
def somename(z):
i = 0
while (....):
a += z[i]
b += z[i+1]
c += z[i+2]
i += 3
In C, z works sort of like an array index, except it starts at whatever the address of the start of the array is, rather than starting at 0. There is no analogous concept in Python, so you need to use a list index explicitly.
Whatever is inside (....) will need modification too. I'll leave that as an exercise for you, since it's unspecified in the question.
A similar code snippet in Python might be:
def somename(z):
i = 0
while (....):
a += z[i]
b += z[i+1]
c += z[i+2]
i += 3
In C, z works sort of like an array index, except it starts at whatever the address of the start of the array is, rather than starting at 0. There is no analogous concept in Python, so you need to use a list index explicitly.
Whatever is inside (....) will need modification too. I'll leave that as an exercise for you, since it's unspecified in the question.
What z += 3 means is basically advance the pointer 3 elements down. Say you have a pointer to an array in C called lst which contains [1, 2, 3, 4]. The pointer lst points to the first element such that *lst is equivalent to lst[0]. Furthermore, *(lst+1) is equivalent to lst[1].
The + operator is implemented via the __add__() method on the left operand, or the __radd__() method on the right operand.
Here.
There are two potential issues.
First, you seem to be relying on your __getattribute__ implementation to let the interpreter find the right __add__ method. Unfortunately, I have noticed that the Python interpreter often has trouble finding special functions, like __add__ or __call__ if they are created on the fly (that is, not made an explicit part of the class when the class is defined). The manuals explicitly acknowledge this, at least for new-style classes:
For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary.
although it seems to me that I have had problems with similar tricks even with old-style classes.
Second, just redirecting __add__ won't be enough. Even if the interpreter successfully reduces
a + b
to
float.__add__( 1.22, b )
the float class still doesn't know how to add a float to a ref. So your __add__ will have to explicitly dereference the target (and dereference that if it's an indirect reference (and dereference that...) Like so:
class ref:
def __init__(self, obj):
self.obj = obj
def get(self): return self.obj
def set(self, obj): self.obj = obj
def __str__(self): return self.obj.__str__()
def __add__( self, other ):
while isinstance( other, ref ):
other = other.obj
return self.obj.__add__( other )
a = ref(1.22)
b = ref(a)
print a
print b
print a + b
The while loop in __add__makes sure that you've unpacked all of the nested refs all the way to the base object.
If I were doing this, and I have used similar constructs to implement proxy patterns, I would refactor so that the while loop is in its own method, say getBaseObject(), and then is called from every time we need the object that is at the actual base of the chain of refs.
As you're aware, Python's slice syntax makes a copy, so in order to manipulate a subsection of a list (not "array", in Python) in place, you need to pass around both the list and the start-index and size (or end-index) of the portion under discussion, much as you could in C. The signature of the recursive function would be something like:
def quicksort( inputList, numElems, startIndex = 0 ):
And the recursive call would be something like:
quicksort( inputList, numElems-last-1, last+1 )
Throughout the function you'd add startIndex to whatever list accesses you would make.
I suppose if you want to do something like that you could do the following:
# list we want to mutate
sort_list = [1,2,3,4,5,6,7,8,9,0]
#wrapper just so everything looks pretty, process could go here if we wanted
def wrapper(a, numlems):
cut = len(a) - numlems
# overwrites a part of the list with another one
a[cut:] = process(a[cut:])
# processing of the slice
def process(a):
# just to show it works
a[1] = 15
return a
wrapper(sort_list, 2)
print(sort_list)
wrapper(sort_list, 4)
print(sort_list)
wrapper(sort_list, 6)
print(sort_list)
This is probably considered pretty evil in python and I wouldn't really recommend it, but it does emulate the functionality you wanted.
For python you only really need:
def quicksort(inputList, startIndex):
Then creating and concatenating slices would work fine without the need for pointer like functionality.
This can be done explicitly.
class ref:
def __init__(self, obj): self.obj = obj
def get(self): return self.obj
def set(self, obj): self.obj = obj
a = ref([1, 2])
b = a
print(a.get()) # => [1, 2]
print(b.get()) # => [1, 2]
b.set(2)
print(a.get()) # => 2
print(b.get()) # => 2
You may want to read Semantics of Python variable names from a C++ perspective. The bottom line: All variables are references.
More to the point, don't think in terms of variables, but in terms of objects which can be named.
Maybe something like this:
self.position = [0.0 for _ in self.total_items * self.xyz]
for i in range(self.components):
self.comps[i].position = self.p_offset
self.p_offset += self.comps[i].items
In Python, you can change values inside a class instance variable. This is called "mutating" the instance. If the class doesn't allow this, it is an "immutable" class; if it does allow this, it is a "mutable" class. Strings are immutable, as are integers, but lists are mutable.
In Python, there is no way that I can think of to get a reference to the middle part of a list. Lists are mutable: things can be inserted, deleted, etc. What should the reference do then?
So instead of doing pointer math and storing a reference to a spot within a list, you should just store the offset, and then use the offset to index the list when you need to reference that spot in the list.
For your specific question:
self.comps[N].position = [1,2,3,4]
This would rebind the name position inside the self.comps[N] object to now point to a newly created list instance with the value [1, 2, 3, 4] and would not affect self.position at all. However, if you just set self.comps[i].position to index values you could use this code:
i = self.comps[N].position
lst = [1, 2, 3, 4]
self.position[i:i+len(lst)] = lst
This would use a "slice" into the self.position list to replace the values.
Note that if you use SciPy or even just NumPy, you can define a numpy.array which is not dynamic; and you can use "views" to get a reference to just part of the list. You might want to look into that, especially if you are working with really large arrays or matrices.
View onto a numpy array?
self.comps[N].position = [1,2,3,4]
will set self.comps[N].position to be a new list. If there are other references to the old list that was self.comps[N].position, they will not be changed.
Example
x=[1,2,3]
y=x
print y #[1, 2, 3]
x[1]=4
print y #[1, 4, 3]
x=[4,5,6]
print y #[1, 4, 3]
create_string_buffer gives you a ctypes object (an array of chars), then byref, and I quote,
Returns a light-weight pointer to obj, which must be an instance of a ctypes type. offset defaults to zero, and must be an integer that will be added to the internal pointer value.
The offset argument has been added in 2.6, so if you're stuck with an older version you will unfortunately need more work.
You can also use ctypes.cast(buf, ctypes.c_void_p)
Your Data looks like it is probably UTF-16. I made a quick C program that looks kind of like your question description and played around a little in the interactive Python interpreter. I think this might be enough to point you in the right direction for writing your own formatter?
int main ()
{
struct String *mystr = AllocateString();
mystr->AllocatorInstance.len = 10;
mystr->AllocatorInstance.Data = (void *) malloc (10);
memset (mystr->AllocatorInstance.Data, 0, 10);
((char *)mystr->AllocatorInstance.Data)[0] = 'h';
((char *)mystr->AllocatorInstance.Data)[2] = 'e';
((char *)mystr->AllocatorInstance.Data)[4] = 'l';
((char *)mystr->AllocatorInstance.Data)[6] = 'l';
((char *)mystr->AllocatorInstance.Data)[8] = 'o';
FreeString (mystr);
}
Using the lldb.frame, lldb.process shortcuts (only valid when doing interactive script), we can read the Data into a python string buffer easily:
>>> valobj = lldb.frame.FindVariable("mystr")
>>> address = valobj.GetChildMemberWithName('AllocatorInstance').GetChildMemberWithName('Data').GetValueAsUnsigned()
>>> size = valobj.GetChildMemberWithName('AllocatorInstance').GetChildMemberWithName('len').GetValueAsUnsigned()
>>> print address
4296016096
>>> print size
10
>>> err = lldb.SBError()
>>> print err
error: <NULL>
>>> membuf = lldb.process.ReadMemory (address, size, err)
>>> print err
success
>>> membuf
'h\x00e\x00l\x00l\x00o\x00'
From this point you can do any of the usual python array type things -
>>> for b in membuf:
... print ord(b)
...
104
0
101
0
108
0
108
0
111
0
I'm not sure how you can tell Python that this is UTF-16 and should be internalized correctly as wide-chars, that's more a Python question than lldb question -- but I think your best bet here is to not use the SBValue methods (because your Data pointer has an uninformative type like void *, like I did in my test program), but to use the SBProcess memory read method.
Without any source code references, this issue is a little harder to figure out than it should be.
With that said, my first bet is going to be that your Char* type is an “opaque” reference, so when you go to dereference it LLDB knows nothing about the pointee type and can’t resolve it. Or maybe the pointee type is not a basic type (int, char, float, …) and as such does not have a value (values are essentially a scalar property, a structure or a class or a union do not have values, they have members)
Can you publish the definition of your string type?
Working from there, there are a couple ways to extract a chunk of data from a memory location. Is your string ASCII/UTF8 encoded? If so, you could just use Process.ReadCStringFromMemory giving it the value of the pointer. That would read until the first 0 terminator is found, or until a certain maximum length is reached (you want that to avoid reading unbounded amounts of data from garbled memory)
If that is not the case, there are other approaches.
Again, the more information you can provide about the internals of your data structure, the easier it gets to write a formatter for it.
There's no way you can do that changing only that line. You can do:
a = [1]
b = a
a[0] = 2
b[0]
That creates a list, assigns the reference to a, then b also, uses the a reference to set the first element to 2, then accesses using the b reference variable.
I want
form.data['field']andform.field.valueto always have the same value
This is feasible, because it involves decorated names and indexing -- i.e., completely different constructs from the barenames a and b that you're asking about, and for with your request is utterly impossible. Why ask for something impossible and totally different from the (possible) thing you actually want?!
Maybe you don't realize how drastically different barenames and decorated names are. When you refer to a barename a, you're getting exactly the object a was last bound to in this scope (or an exception if it wasn't bound in this scope) -- this is such a deep and fundamental aspect of Python that it can't possibly be subverted. When you refer to a decorated name x.y, you're asking an object (the object x refers to) to please supply "the y attribute" -- and in response to that request, the object can perform totally arbitrary computations (and indexing is quite similar: it also allows arbitrary computations to be performed in response).
Now, your "actual desiderata" example is mysterious because in each case two levels of indexing or attribute-getting are involved, so the subtlety you crave could be introduced in many ways. What other attributes is form.field suppose to have, for example, besides value? Without that further .value computations, possibilities would include:
class Form(object):
...
def __getattr__(self, name):
return self.data[name]
and
class Form(object):
...
@property
def data(self):
return self.__dict__
The presence of .value suggests picking the first form, plus a kind-of-useless wrapper:
class KouWrap(object):
def __init__(self, value):
self.value = value
class Form(object):
...
def __getattr__(self, name):
return KouWrap(self.data[name])
If assignments such form.field.value = 23 is also supposed to set the entry in form.data, then the wrapper must become more complex indeed, and not all that useless:
class MciWrap(object):
def __init__(self, data, k):
self._data = data
self._k = k
@property
def value(self):
return self._data[self._k]
@value.setter
def value(self, v)
self._data[self._k] = v
class Form(object):
...
def __getattr__(self, name):
return MciWrap(self.data, name)
The latter example is roughly as close as it gets, in Python, to the sense of "a pointer" as you seem to want -- but it's crucial to understand that such subtleties can ever only work with indexing and/or decorated names, never with barenames as you originally asked!