I'm trying to create simple bindings to the MD4C project but get a weird segmentation fault thrown when I attempt to call md_parse. I'm not too well versed in C so the code bellow describes my best attempt to tackle this issue. I acquired libmd4c.dylib by cloning and building the project with cmake according to their instructions:
brew install cmake
git clone https://github.com/mity/md4c.git
cd md4c
mkdir build
cd build
cmake ..
make
My best guess about what's wrong is the actual arguments I'm passing to the final call. Here is the full code:
import ctypes
import sys
lib = ctypes.CDLL('libmd4c.dylib')
def generic_cb(*args, **kwargs):
print(args, kwargs)
def block_cb(code, detail, udata):
generic_cb(code, details, udata)
return 0
c_func_block_cb = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.c_uint,
ctypes.c_void_p,
ctypes.c_void_p
)
c_func_block_cb_p = ctypes.POINTER(
c_func_block_cb
)
c_func_text_cb = ctypes.CFUNCTYPE(
ctypes.c_int,
ctypes.c_wchar_p,
ctypes.c_uint,
ctypes.c_void_p
)
c_func_text_cb_p = ctypes.POINTER(
c_func_text_cb
)
c_func_debug_log_cb = ctypes.CFUNCTYPE(
ctypes.c_void_p,
ctypes.c_char_p,
ctypes.c_void_p,
)
c_func_debug_log_cb_p = ctypes.POINTER(
c_func_debug_log_cb
)
c_func_syntax_cb = ctypes.CFUNCTYPE(
ctypes.c_void_p,
ctypes.c_void_p,
)
c_func_syntax_cb_p = ctypes.POINTER(
c_func_syntax_cb
)
class Structure(ctypes.Structure):
_fields_ = [
(
'abi_version',
ctypes.c_uint
),
(
'flags',
ctypes.c_uint
),
(
'enter_block',
c_func_block_cb_p
),
(
'leave_block',
c_func_block_cb_p
),
(
'enter_span',
c_func_block_cb_p
),
(
'leave_span',
c_func_block_cb_p
),
(
'text',
c_func_text_cb_p
),
(
'debug_log',
c_func_debug_log_cb_p
),
(
'syntax',
c_func_syntax_cb_p
)
]
StructurePointer = ctypes.POINTER(Structure)
c_block_cb = c_func_block_cb(block_cb)
c_block_cb_p = c_func_block_cb_p(c_block_cb)
c_text_cb = c_func_text_cb(generic_cb)
c_text_cb_p = c_func_text_cb_p(c_text_cb)
c_debug_log_cb = c_func_debug_log_cb(generic_cb)
c_debug_log_cb_p = c_func_debug_log_cb_p(c_debug_log_cb)
c_syntax_cb = c_func_syntax_cb(generic_cb)
c_syntax_cb_p = c_func_syntax_cb_p(c_syntax_cb)
struct = Structure(
0,
0,
c_block_cb_p,
c_block_cb_p,
c_block_cb_p,
c_block_cb_p,
c_text_cb_p,
c_debug_log_cb_p,
None
)
value = '**hello**'
value_p = ctypes.c_wchar_p(value)
struct_p = StructurePointer(struct)
size = ctypes.c_uint(len(value))
func = lib.md_parse
func.argtypes = [
ctypes.c_wchar_p,
ctypes.c_uint,
StructurePointer,
ctypes.c_void_p
]
func.restype = ctypes.c_int
func.errcheck = print
udata = ctypes.c_int()
udata_p = ctypes.byref(udata)
result = lib.md_parse(value_p, size, struct_p, udata_p)
print(result)
Please let me know if you have any insights to share.
udata_pis a reference to ac_int, butfunc.argtypesearlier indicates it should be aStructurePointer. Without an minimal reproducible example that's all I see.