Skip to content

Instantly share code, notes, and snippets.

@marianoguerra
Created August 7, 2012 04:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marianoguerra/3281751 to your computer and use it in GitHub Desktop.
Save marianoguerra/3281751 to your computer and use it in GitHub Desktop.
Pypy ctypes struct initialization and assignment bug

Pypy ctypes struct initialization and assignment bug

to setup the example:

mkdir pypy-ctypes-bug
cd pypy-ctypes-bug
git clone https://github.com/hcatlin/libsass.git
cd libsass
./configure && make
cd ..
vim sass.py # copy the code below

versions:

pypy:

Python 2.7.2 (341e1e3821ff, Jun 07 2012, 15:40:31)
[PyPy 1.9.0 with GCC 4.4.3] on linux2

python:

Python 2.7.3 (default, Apr 20 2012, 22:44:07) 
[GCC 4.6.3] on linux2

running it shows that the fields are initialized differently:

pypy:

➜  pypy-ctypes-bug  pypy sass.py
source string: 'None' output string: 'None'
error status: '0' error message: 'None'

python:

➜  pypy-ctypes-bug  python sass.py
source string: '' output string: '�P'
error status: '151547652' error message: 'None'

also, setting a field fails in pypy:

➜  pypy-ctypes-bug  pypy sass.py fail
source string: 'None' output string: 'None'
error status: '0' error message: 'None'
Traceback (most recent call last):
  File "app_main.py", line 51, in run_toplevel
  File "sass.py", line 57, in <module>
    ctx.source_string = ""
  File "/home/mariano/src/soft/pypy-1.9/lib_pypy/_ctypes/structure.py", line 108, in __set__
    store_reference(obj, key, cobj._objects)
  File "/home/mariano/src/soft/pypy-1.9/lib_pypy/_ctypes/basics.py", line 21, in store_reference
    while '_index' in where.__dict__:
AttributeError: 'NoneType' object has no attribute '__dict__'

and not in python:

➜  pypy-ctypes-bug  python sass.py fail
source string: '' output string: '�P'
error status: '164286212' error message: 'None'
➜  pypy-ctypes-bug

code from the example:

#!/usr/bin/env python
from ctypes import *

import sys

LIB_PATH = "libsass/.libs/libsass.so"
LIB = cdll.LoadLibrary(LIB_PATH)

class Options(Structure):
    """
    struct sass_options {
      int output_style;
      char* include_paths;
    };
    """

    def __init__(self, output_style=0 , include_paths=""):
        self.output_style = output_style
        self.include_paths = to_char_array(include_paths)

    _fields_ = [
        ("output_style", c_int),
        ("include_paths", c_char_p)
    ]

class Context(Structure):
    """
    struct sass_context {
      char* source_string;
      char* output_string;
      struct sass_options options;
      int error_status;
      char* error_message;
    };
    """

    _fields_ = [
        ("source_string", c_char_p),
        ("output_string", c_char_p),
        ("options", Options),
        ("error_status", c_int),
        ("error_message", c_char_p)
    ]

_new_context = LIB.sass_new_context
_new_context.argtypes = []
_new_context.restype = Context

if __name__ == "__main__":
    ctx = _new_context()
    print "source string: '%s' output string: '%s'" % (
            ctx.source_string, ctx.output_string)
    print "error status: '%d' error message: '%s'" % (
            ctx.error_status, ctx.error_message)

    if len(sys.argv) > 1 and sys.argv[1] == "fail":
        ctx.source_string = ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment