Fix segfault issue
I think we need to keep a reference to the ctypes voidp object that we pass as userdata alive
This commit is contained in:
104
weaseljson.py
104
weaseljson.py
@@ -33,52 +33,7 @@ class WeaselJsonStatus(enum.Enum):
|
|||||||
OVERFLOW = 3
|
OVERFLOW = 3
|
||||||
|
|
||||||
|
|
||||||
class WeaselJsonParserBase:
|
class WeaselJsonCallbacksBase:
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
build_dir: Optional[str] = None,
|
|
||||||
stackSize: int = 1024,
|
|
||||||
) -> None:
|
|
||||||
self._lib = None
|
|
||||||
if build_dir is None:
|
|
||||||
build_dir = os.path.dirname(__file__) + "/build"
|
|
||||||
for f in (build_dir + "/" + "libweaseljson.so",):
|
|
||||||
try:
|
|
||||||
self._lib = ctypes.cdll.LoadLibrary(f)
|
|
||||||
except OSError:
|
|
||||||
print("Could not load " + f)
|
|
||||||
pass
|
|
||||||
|
|
||||||
if self._lib is None:
|
|
||||||
import sys
|
|
||||||
|
|
||||||
print(
|
|
||||||
"Could not find libweaseljson implementation",
|
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
self._lib.WeaselJsonParser_create.argtypes = (
|
|
||||||
ctypes.c_int,
|
|
||||||
ctypes.POINTER(WeaselJsonCallbacks),
|
|
||||||
ctypes.c_void_p,
|
|
||||||
)
|
|
||||||
self._lib.WeaselJsonParser_create.restype = ctypes.c_void_p
|
|
||||||
self._lib.WeaselJsonParser_reset.argtypes = (ctypes.c_void_p,)
|
|
||||||
self._lib.WeaselJsonParser_destroy.argtypes = (ctypes.c_void_p,)
|
|
||||||
self._lib.WeaselJsonParser_parse.argtypes = (
|
|
||||||
ctypes.c_void_p,
|
|
||||||
ctypes.c_void_p,
|
|
||||||
ctypes.c_int,
|
|
||||||
)
|
|
||||||
self._lib.WeaselJsonParser_parse.restype = WeaselJsonStatus
|
|
||||||
|
|
||||||
self.p = self._lib.WeaselJsonParser_create(
|
|
||||||
stackSize,
|
|
||||||
callbacks,
|
|
||||||
ctypes.cast(ctypes.pointer(ctypes.py_object(self)), ctypes.c_void_p),
|
|
||||||
)
|
|
||||||
|
|
||||||
def on_begin_object(self):
|
def on_begin_object(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -118,6 +73,57 @@ class WeaselJsonParserBase:
|
|||||||
def on_null_literal(self):
|
def on_null_literal(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class WeaselJsonParser:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
callbacks: WeaselJsonCallbacksBase,
|
||||||
|
build_dir: Optional[str] = None,
|
||||||
|
stackSize: int = 1024,
|
||||||
|
) -> None:
|
||||||
|
self._lib = None
|
||||||
|
if build_dir is None:
|
||||||
|
build_dir = os.path.dirname(__file__) + "/build"
|
||||||
|
for f in (build_dir + "/" + "libweaseljson.so",):
|
||||||
|
try:
|
||||||
|
self._lib = ctypes.cdll.LoadLibrary(f)
|
||||||
|
except OSError:
|
||||||
|
print("Could not load " + f)
|
||||||
|
pass
|
||||||
|
|
||||||
|
if self._lib is None:
|
||||||
|
import sys
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Could not find libweaseljson implementation",
|
||||||
|
file=sys.stderr,
|
||||||
|
)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
self._lib.WeaselJsonParser_create.argtypes = (
|
||||||
|
ctypes.c_int,
|
||||||
|
ctypes.POINTER(WeaselJsonCallbacks),
|
||||||
|
ctypes.c_void_p,
|
||||||
|
)
|
||||||
|
self._lib.WeaselJsonParser_create.restype = ctypes.c_void_p
|
||||||
|
self._lib.WeaselJsonParser_reset.argtypes = (ctypes.c_void_p,)
|
||||||
|
self._lib.WeaselJsonParser_destroy.argtypes = (ctypes.c_void_p,)
|
||||||
|
self._lib.WeaselJsonParser_parse.argtypes = (
|
||||||
|
ctypes.c_void_p,
|
||||||
|
ctypes.c_void_p,
|
||||||
|
ctypes.c_int,
|
||||||
|
)
|
||||||
|
self._lib.WeaselJsonParser_parse.restype = WeaselJsonStatus
|
||||||
|
self.voidp_callbacks = ctypes.cast(
|
||||||
|
ctypes.pointer(ctypes.py_object(callbacks)), ctypes.c_void_p
|
||||||
|
)
|
||||||
|
|
||||||
|
self.p = self._lib.WeaselJsonParser_create(
|
||||||
|
stackSize,
|
||||||
|
c_callbacks,
|
||||||
|
self.voidp_callbacks,
|
||||||
|
)
|
||||||
|
|
||||||
def parse(self, data: bytes) -> WeaselJsonStatus:
|
def parse(self, data: bytes) -> WeaselJsonStatus:
|
||||||
buf = (ctypes.c_ubyte * len(data)).from_buffer(bytearray(data))
|
buf = (ctypes.c_ubyte * len(data)).from_buffer(bytearray(data))
|
||||||
return self._lib.WeaselJsonParser_parse(self.p, buf, len(data))
|
return self._lib.WeaselJsonParser_parse(self.p, buf, len(data))
|
||||||
@@ -215,7 +221,7 @@ def on_null_literal(p):
|
|||||||
self.on_null_literal()
|
self.on_null_literal()
|
||||||
|
|
||||||
|
|
||||||
callbacks = WeaselJsonCallbacks(
|
c_callbacks = WeaselJsonCallbacks(
|
||||||
on_begin_object,
|
on_begin_object,
|
||||||
on_end_object,
|
on_end_object,
|
||||||
on_begin_string,
|
on_begin_string,
|
||||||
@@ -232,13 +238,13 @@ callbacks = WeaselJsonCallbacks(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class JsonParser(WeaselJsonParserBase):
|
class MyCallbacks(WeaselJsonCallbacksBase):
|
||||||
# override callbacks
|
# override callbacks
|
||||||
def on_string_data(self, data):
|
def on_string_data(self, data):
|
||||||
print(data)
|
print(data)
|
||||||
|
|
||||||
|
|
||||||
with JsonParser() as parser:
|
with WeaselJsonParser(MyCallbacks()) as parser:
|
||||||
raw = json.dumps({"hello": "world", "foo": 42}).encode()
|
raw = json.dumps({"hello": "world", "foo": 42}).encode()
|
||||||
i = 0
|
i = 0
|
||||||
stride = 1
|
stride = 1
|
||||||
|
|||||||
Reference in New Issue
Block a user