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.


    Trouble with OpenGL/Ctypes and Pythonista

    Pythonista
    3
    7
    4608
    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.
    • rovitotv
      rovitotv last edited by

      Greetings,
      I am having a heck of a time trying to get a simple OpenGL example to run....this is an example that I have used on the Mac and Raspberry Pi that just draws a simple triangle. I started with example code from @omz then got stuck on the function glShaderSource. My code is on GitHub and it fails on line 86 with the error message "ctypes.ArgumentError: argument 3: <class 'TypeError'>: wrong type".

      Any help you can provide would be much appreciated. I am using Python 2.7 with the latest version of Pythonista. Thanks!

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

        You have commented out the lines that set the argtypes. It is expecting a c_void_p (by default, i think), you are giving it a character array.

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

          I think if argtypes are not set, ctypes guesses the type based on what arguments you give. For example an int becomes a c_int. The default argtypes guesses are often incorrect, so it's a good idea to set the argtypes explicitly. If you do that and you get a TypeError, that means you're not passing an object of the right type.

          In this case here, it looks like you're overthinking things a little when creating the char array :) In your code you write char_arr = (c_char_p * len(shader_source)). c_char_p stands for char *, so in this case you're creating an array of char *s with len(shader_source) elements. If you want to create a fixed-length char array, you should use c_char as the element type (e. g. c_char * len(shader_source)). But in this case I think you don't need to do any manual conversion at all - ctypes can automatically convert a Python bytes object to a c_char_p, so if you set the function's argtypes correctly, you can pass it the bytes object directly.

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

            Thanks JonB uncommenting argtypes and giving it a c_void_p it is now working....I have a different error but at least I got past that line. Thank you!

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

              Thank you both @dgelessus and @JonB !! ..... I use to be good at C but Python has spoiled me :-). Without the OpenGLES-Pythonista project I am not even sure I would of gotten this far. What confuses me is I can't just pass glShaderSource a c-string with the shader code it is an array of string pointers, OpenGL ES function definition

              But your answer(s) at least got me further down the road and I will continue to explore.

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

                Ah, if the third parameter really is a char **, that's a different story - I don't know anything about OpenGL and its APIs, so I assumed the double pointer was by accident.

                In that case, first of all you should set the argtypes appropriately, it will make calling the function much cleaner:

                c.glShaderSource.restype = None
                c.glShaderSource.argtypes = [GLuint, GLsizei, POINTER(c_char_p), POINTER(GLint)]
                

                Now you can call the function like this:

                c.glShaderSource(shader, 1, byref(cast(source, c_char_p)), None)
                

                Since the argtypes are set, the integer arguments don't need to be manually wrapped in the required types.

                byref behaves like the & operator in C, it returns the address of the given object (which in this case creates a char **). The cast to c_char_p is necessary because byref doesn't perform any automatic conversions on its argument.

                The length argument is None (C NULL), which according to the documentation means that all source strings are zero-terminated (which is the case for all C strings created by ctypes).

                rovitotv 1 Reply Last reply Reply Quote 0
                • rovitotv
                  rovitotv @dgelessus last edited by

                  @dgelessus thanks again!!!! That is much more elegant than the code I was using. I have now carefully gone through all the argtypes with the OpenGL function I was going to use and made sure they are correct. I have updated the code on github. Thanks!

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