Debugging Python ctypes segmentation fault
Question: I am trying to port some Python ctypes code from a Windows-specific program to
link with a Linux port of my library. The shortest Python code sample that
describes my problem is shown below. When I try to execute it, I receive a
segmentation fault in examine_arguments() in Python. I placed a printf
statement in my library at the crashing function call, but it is never
executed, which leads me to think the problem is in the ctypes code.

    
    
    import ctypes
    
    avidll = ctypes.CDLL("libavxsynth.so")
    
    
    class AVS_Value(ctypes.Structure, object):
        def __init__(self, val=None):
            self.type=ctypes.c_short(105) # 'i'
            self.array_size = 5
            self.d.i = 99
    
    
    class U(ctypes.Union):
        _fields_ = [("c", ctypes.c_void_p),
                    ("b", ctypes.c_long),
                    ("i", ctypes.c_int),
                    ("f", ctypes.c_float),
                    ("s", ctypes.c_char_p),
                    ("a", ctypes.POINTER(AVS_Value))]
    
    
    AVS_Value._fields_ = [("type", ctypes.c_short),
                          ("array_size", ctypes.c_short),
                          ("d", U)]
    
    
    avs_create_script_environment = avidll.avs_create_script_environment
    avs_create_script_environment.restype = ctypes.c_void_p
    avs_create_script_environment.argtypes = [ctypes.c_int]
    
    avs_set_var = avidll.avs_set_var
    avs_set_var.restype = ctypes.c_int
    avs_set_var.argtypes = [ctypes.c_void_p, ctypes.c_char_p, AVS_Value]
    
    
    env = avs_create_script_environment(2)
    val = AVS_Value()
    res = avs_set_var(env, b'test', val)
    

My library has the following in its headers, and a plain-C program doing what
I describe above (calling create_script_environment followed by set_var) runs
fine. Looking at logging information my library is putting onto the console,
the crash happens when I try to enter avs_set_var.

    
    
    typedef struct AVS_ScriptEnvironment AVS_ScriptEnvironment;
    typedef struct AVS_Value AVS_Value;
    struct AVS_Value {
      short type;  // 'a'rray, 'c'lip, 'b'ool, 'i'nt, 'f'loat, 's'tring, 'v'oid, or 'l'ong
                   // for some function e'rror
      short array_size;
      union {
        void * clip; // do not use directly, use avs_take_clip
        char boolean;
        int integer;
        float floating_pt;
        const char * string;
        const AVS_Value * array;
      } d;
    };
    AVS_ScriptEnvironment * avs_create_script_environment(int version);
    int avs_set_var(AVS_ScriptEnvironment *, const char* name, AVS_Value val);
    

I tried backtracing the call from GDB, but I don't understand how to interpret
the results nor really much about using GDB.

    
    
    #0  0x00007ffff61d6490 in examine_argument () from /usr/lib/python2.7/lib-dynload/_ctypes.so
    #1  0x00007ffff61d65ba in ffi_prep_cif_machdep () from /usr/lib/python2.7/lib-dynload/_ctypes.so
    #2  0x00007ffff61d3447 in ffi_prep_cif () from /usr/lib/python2.7/lib-dynload/_ctypes.so
    #3  0x00007ffff61c7275 in _ctypes_callproc () from /usr/lib/python2.7/lib-dynload/_ctypes.so
    #4  0x00007ffff61c7aa2 in PyCFuncPtr_call.2798 () from /usr/lib/python2.7/lib-dynload/_ctypes.so
    #5  0x00000000004c7c76 in PyObject_Call ()
    #6  0x000000000042aa4a in PyEval_EvalFrameEx ()
    #7  0x00000000004317f2 in PyEval_EvalCodeEx ()
    #8  0x000000000054b171 in PyRun_FileExFlags ()
    #9  0x000000000054b7d8 in PyRun_SimpleFileExFlags ()
    #10 0x000000000054c5d6 in Py_Main ()
    #11 0x00007ffff68e576d in __libc_start_main () from /lib/x86_64-linux-gnu/libc.so.6
    #12 0x000000000041b931 in _start ()
    

I'm at a loss as to how to approach this problem. I've looked at the details
of the calling types, but I don't see anything obviously incorrect there. Am I
falling into any platform-specific usages of types?

**Edit** It seems there's a problem with 32-bit vs 64-bit architectures in the
ctypes module. When I tested this again with a 32-bit build of my library and
32-bit Python, it ran successfully. On 64-bit, it segfaults at the same place.


Answer: Try using `c_void_p` for the opaque `AVS_ScriptEnvironment*`:

    
    
    avs_create_script_environment.restype = c_void_p
    

and:

    
    
    avs_set_var.argtypes=[c_void_p,ctypes.c_char_p,AVS_Value]
    

