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 = ""