omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    4
    18
    10127
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • omz
      omz last edited by omz

      The type encoding parser doesn't support unions (which are pretty rare in Obj-C). You might need to pass restype and argtypes explicitly.

      1 Reply Last reply Reply Quote 0
      • Cethric
        Cethric last edited by

        Thank you @JonB and @omz for your help
        As @omz said the encoding parser does not support unions so for simplicity I have made a wrapper class for GLKEffectPropertyLight, and will be doing so probably for the majority of GLKit.
        When I have the majority of it up and running I will update the GitHub repo.

        Thank you for the help

        1 Reply Last reply Reply Quote 0
        • Cethric
          Cethric last edited by

          After further test this does not actually resolve the issue, as it now just returns a pointer to the structure (ie the first element of GLKVector4 is now the pointer)
          Any ideas on how to fix this?

          1 Reply Last reply Reply Quote 0
          • ccc
            ccc last edited by ccc

            Could a Python memoryview be used to serve similar purpose to an Objective C union?

            1 Reply Last reply Reply Quote 0
            • Cethric
              Cethric last edited by

              I have never used a memoryview object before so I am not entirely sure how to implement/use it however I would assume that it would be the same way I did for a Structure or any other ctypes object (is this correct?)

              I will look into it and see whether it helps.
              Thanks for the info

              1 Reply Last reply Reply Quote 0
              • Cethric
                Cethric last edited by

                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

                1 Reply Last reply Reply Quote 0
                • JonB
                  JonB last edited by

                  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.)

                  1 Reply Last reply Reply Quote 0
                  • Cethric
                    Cethric last edited by

                    Can you please elaborate on what you mean.
                    Using the current OpenGLES repo under GLKit/light.py
                    in GLKEffectPropertyLight.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
                    
                    1 Reply Last reply Reply Quote 0
                    • JonB
                      JonB last edited by

                      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
                      
                      1 Reply Last reply Reply Quote 0
                      • JonB
                        JonB last edited by JonB

                        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.

                        1 Reply Last reply Reply Quote 0
                        • ccc
                          ccc last edited by

                          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?

                          1 Reply Last reply Reply Quote 0
                          • Cethric
                            Cethric last edited by

                            @JonB I don't know what you are doing differently to me, but I can't seem to get it to work. (iPad Mini 2, iOS 9.1 (13B5110e))
                            @ccc I am not entirely sure what you mean.

                            1 Reply Last reply Reply Quote 0
                            • JonB
                              JonB last edited by

                              @Cethric. Did my example work for you? If not, what happened?

                              Can you describe your problem more specifically? are you crashing, or just unable to get/set position?

                              @ccc I don't think so. The memory in question is on the heap, and completely nonexecutable.

                              1 Reply Last reply Reply Quote 0
                              • Cethric
                                Cethric last edited by

                                @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 and cast should all be the same, shouldn't they?

                                1 Reply Last reply Reply Quote 0
                                • omz
                                  omz last edited by

                                  @Cethric I was able to get @JonB's example to work by replacing restype=glk4_union with restype=glk4 when reading back the position.

                                  1 Reply Last reply Reply Quote 0
                                  • Cethric
                                    Cethric last edited by

                                    @omz that seemed to fix it. Thanks

                                    1 Reply Last reply Reply Quote 0
                                    • First post
                                      Last post
                                    Powered by NodeBB Forums | Contributors