Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
How to use structures? setting GLKEffectPropertyLight.position, fails
-
I have done a bit more testing and noticed that this is only an issue for GLKVector(2|3|4) and not for any of the GLKMatrix structures.
I have also updated the Github repo -
you should be able to cast the result as a POINTER(GLKVector3), then access the .contents().
I have been working on extending the objc utils to handle union encoding types, though it is not quite working yet (i can generate the structure from the type encoding, but using that as a restype seems to crash.)
-
Can you please elaborate on what you mean.
Using the current OpenGLES repo under GLKit/light.py
inGLKEffectPropertyLight.getPosition
I have tried both setting the return type and argtypes, but neither seem to work.def getPosition(self): p = GLKVector4() self._light.position(ctypes.byref(p), argtypes=[ctypes.POINTER(GLKVector4)], restype=None) res = self._light.position(argtypes=[], restype=ctypes.POINTER(GLKVector4)) print p return res.contents
-
Something strange seems to be happening in either ctypes, or objc with union return types. At least, on 32 bit, which uses objc_msgSend_stret. That function works by taking in a pointer to an existing structure, and modifying it in place.
It seems as if the size of the object returned is larger than what is passed in as the restype, causing a crash when the correct structure is used. Oddly, it seems like it does not always crash, for instance sometimes when calling l.position() with no left hand side, i was able to get a result.
A workaround is to pass in a larger structure for the return type, to ensure nothing gets overwritten. if you want to pass the struct back to objc, however, you must pass the right size, so you can use cast to cast to to correct type. This should work with your Union types as well. You must use the argtypes/restype input to override these.
from objc_util import * PropLight = ObjCClass('GLKEffectPropertyLight') # I will rename it later. l = PropLight.alloc().init() glk4 = parse_struct('{glkvec4=ffff}') glk4_union = parse_struct('{glkvec4union=fffff}') #union seems to have an extra field.... # test code: newpos=glk4() newpos.a=1. newpos.b=2. newpos.c=3. newpos.d=4. l.setPosition_(newpos,restype=ctypes.c_void_p, argtypes=[glk4]) # read back position, then cast to correct type retpos=l.position(restype=glk4_union, argtypes=[]) pos=ctypes.cast(ctypes.pointer(retpos),ctypes.POINTER(glk4)).contents print 'original', newpos.a,newpos.b, newpos.c, newpos.d print 'returned', retpos.a, retpos.b, retpos.c, retpos.d print 'cast', pos.a, pos.b, pos.c, pos.d
-
btw, if you are 64 bit, i suspect you can just use position() with restype= GLKVector4 and argtypes=[]. i suspect the extra size trick is needed only for 32 bit. Note you need to use setPosition_ to set.
-
Is it possible that you have discovered an overwrite condition in Apple's API that could be used as an exploit by a dishonest coder?
-
-
-
@JonB I am unable to get, I don't not if setting is working either. Using the example you provided I get
original 1.0 2.0 3.0 4.0 returned 9.45935362045e+19 1.40129846432e-45 2.80259692865e-45 0.0 cast 9.45935362045e+19 1.40129846432e-45 2.80259692865e-45 0.0
However
original
,returned
andcast
should all be the same, shouldn't they? -
-
@omz that seemed to fix it. Thanks