Closed jameslewis4891 closed 1 year ago
ctypes.create_string_buffer
uses ctypes.c_char
as the underlying type, which is a signed char
. The unsigned char
type in ctypes
is ctypes.c_ubyte
.
I don't have access to the above code, but here's a working example:
import cppyy, ctypes
cppyy.cppdef(r"""\
void func(unsigned char* s) {
s[0] = 'a'; s[1] = 'b'; s[2] = 'c';
}""");
recvbuf = (ctypes.c_ubyte*1024)()
cppyy.gbl.func(recvbuf)
for i in range(3):
print(chr(recvbuf[i]))
It may seem pedantic to care about char
signedness, but contrary to binding modern C++ code, low-level C code offers basically no clues to an automatic bindings generator to figure out allowable conversions. In particular, unsigned char
is often not used as a character type and thus shouldn't (and isn't) be considered a string.
Thanks @wlav progress. I'm now getting a *** Break *** segmentation violation
Code
def get_printer_status():
cppyy.include("CeSmLm.h")
cppyy.load_library("libCeSmLm")
printer = cppyy.gbl
print(f"libCeSmLm version {printer.GetLibVers()}")
open_printer_result = printer.openUSBDevice(0x0DD4, 0x0205, "")
if open_printer_result == 0:
recv_buffer = (ctypes.c_ubyte*2024)()
dw_size = 2024
dw_read = 0
result = printer.GetPrinterStatus(recv_buffer, dw_size, dw_read)
y = 0
Result
libCeSmLm version 1.05
*** Break *** segmentation violation
#0 0x00007f2e97b6445a in __GI___wait4 (pid=48122, stat_loc=stat_loc
entry=0x7fff2e23a228, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1 0x00007f2e97b6441b in __GI___waitpid (pid=<optimised out>, stat_loc=stat_loc
entry=0x7fff2e23a228, options=options
entry=0) at ./posix/waitpid.c:38
#2 0x00007f2e97acabcb in do_system (line=<optimised out>) at ../sysdeps/posix/system.c:171
#3 0x00007f2e97000725 in CppyyLegacy::TUnixSystem::StackTrace() () from /home/james/work/ckp80111/venv/lib/python3.10/site-packages/cppyy_backend/lib/libCoreLegacy.so
#4 0x00007f2e92704863 in (anonymous namespace)::do_trace (sig=1) at src/clingwrapper.cxx:239
#5 (anonymous namespace)::TExceptionHandlerImp::HandleException (this=<optimised out>, sig=1) at src/clingwrapper.cxx:252
#6 0x00007f2e96fff231 in CppyyLegacy::TUnixSystem::DispatchSignals(CppyyLegacy::ESignals) () from /home/james/work/ckp80111/venv/lib/python3.10/site-packages/cppyy_backend/lib/libCoreLegacy.so
#7 <signal handler called>
#8 0x00007f2e8ec01f71 in CComPortUsb::ReadDeviceIf0(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#9 0x00007f2e8ec01ad7 in CComPortUsb::GetPrinterStatus(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#10 0x00007f2e8ec01763 in GetPrinterStatus(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#11 0x00007f2e97108029 in ?? ()
#12 0x00007fff2e23d6c0 in ?? ()
#13 0x00007f2e9270c85f in WrapperCall (method=94659202771888, nargs=3, args_=0x7fff2e23d410, self=0x0, result=0x7fff2e23d410) at src/clingwrapper.cxx:885
#14 0x00007f2e9270ce17 in CallT<long long> (args=<optimised out>, nargs=<optimised out>, self=<optimised out>, method=<optimised out>) at src/clingwrapper.cxx:930
#15 Cppyy::CallLL (method=<optimised out>, self=<optimised out>, nargs=<optimised out>, args=<optimised out>) at src/clingwrapper.cxx:953
#16 0x00007f2e901f5111 in GILCallLL (ctxt=0x7fff2e23d6a0, self=<optimised out>, method=<optimised out>) at src/Executors.cxx:74
#17 CPyCppyy::(anonymous namespace)::ULongExecutor::Execute (this=<optimised out>, method=<optimised out>, self=<optimised out>, ctxt=0x7fff2e23d6a0) at src/Executors.cxx:273
#18 0x00007f2e901aecf9 in CPyCppyy::CPPMethod::ExecuteFast (self=<optimised out>, offset=<optimised out>, ctxt=0x7fff2e23d6a0, this=<optimised out>, this=<optimised out>) at src/CPPMethod.cxx:123
#19 0x00007f2e901b06c9 in CPyCppyy::CPPMethod::Execute (this=this
entry=0x5617908d73a0, self=self
entry=0x0, offset=offset
entry=0, ctxt=ctxt
entry=0x7fff2e23d6a0) at src/CPPMethod.cxx:892
#20 0x00007f2e901aac7f in CPyCppyy::CPPFunction::Call (this=0x5617908d73a0, self=
0x7fff2e23d638: 0x0, args=<optimised out>, nargsf=<optimised out>, kwds=<optimised out>, ctxt=0x7fff2e23d6a0) at src/CPPFunction.cxx:90
#21 0x00007f2e901b6441 in CPyCppyy::(anonymous namespace)::mp_vectorcall (pymeth=0x7f2e8fadec80, args=0x7f2e8fdeaee8, nargsf=9223372036854775811, kwds=0x0) at src/CPPOverload.cxx:641
#22 0x000056178ca25a72 in _PyEval_EvalFrameDefault ()
#23 0x000056178ca373ac in _PyFunction_Vectorcall ()
#24 0x000056178ca20005 in _PyEval_EvalFrameDefault ()
#25 0x000056178ca1c766 in ?? ()
#26 0x000056178cb14456 in PyEval_EvalCode ()
#27 0x000056178cb40f08 in ?? ()
#28 0x000056178cb39d5b in ?? ()
#29 0x000056178cb40c55 in ?? ()
#30 0x000056178cb40138 in _PyRun_SimpleFileObject ()
#31 0x000056178cb3fe33 in _PyRun_AnyFileObject ()
#32 0x000056178cb310ae in Py_RunMain ()
#33 0x000056178cb0734d in Py_BytesMain ()
#34 0x00007f2e97aa3d90 in __libc_start_call_main (main=main
entry=0x56178cb07310, argc=argc
entry=2, argv=argv
entry=0x7fff2e23dfe8) at ../sysdeps/nptl/libc_start_call_main.h:58
#35 0x00007f2e97aa3e40 in __libc_start_main_impl (main=0x56178cb07310, argc=2, argv=0x7fff2e23dfe8, init=<optimised out>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7fff2e23dfd8) at ../csu/libc-start.c:392
#36 0x000056178cb07245 in _start ()
*** Break *** segmentation violation
#0 0x00007f2e97b6445a in __GI___wait4 (pid=48340, stat_loc=stat_loc
entry=0x7fff2e23a228, options=options
entry=0, usage=usage
entry=0x0) at ../sysdeps/unix/sysv/linux/wait4.c:30
#1 0x00007f2e97b6441b in __GI___waitpid (pid=<optimised out>, stat_loc=stat_loc
entry=0x7fff2e23a228, options=options
entry=0) at ./posix/waitpid.c:38
#2 0x00007f2e97acabcb in do_system (line=<optimised out>) at ../sysdeps/posix/system.c:171
#3 0x00007f2e97000725 in CppyyLegacy::TUnixSystem::StackTrace() () from /home/james/work/ckp80111/venv/lib/python3.10/site-packages/cppyy_backend/lib/libCoreLegacy.so
#4 0x00007f2e927046e7 in (anonymous namespace)::do_trace (sig=1) at src/clingwrapper.cxx:239
#5 (anonymous namespace)::TExceptionHandlerImp::HandleException (this=<optimised out>, sig=1) at src/clingwrapper.cxx:258
#6 0x00007f2e96fff231 in CppyyLegacy::TUnixSystem::DispatchSignals(CppyyLegacy::ESignals) () from /home/james/work/ckp80111/venv/lib/python3.10/site-packages/cppyy_backend/lib/libCoreLegacy.so
#7 <signal handler called>
#8 0x00007f2e8ec01f71 in CComPortUsb::ReadDeviceIf0(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#9 0x00007f2e8ec01ad7 in CComPortUsb::GetPrinterStatus(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#10 0x00007f2e8ec01763 in GetPrinterStatus(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#11 0x00007f2e97108029 in ?? ()
#12 0x00007fff2e23d6c0 in ?? ()
#13 0x00007f2e9270c85f in WrapperCall (method=94659202771888, nargs=3, args_=0x7fff2e23d410, self=0x0, result=0x7fff2e23d410) at src/clingwrapper.cxx:885
#14 0x00007f2e9270ce17 in CallT<long long> (args=<optimised out>, nargs=<optimised out>, self=<optimised out>, method=<optimised out>) at src/clingwrapper.cxx:930
#15 Cppyy::CallLL (method=<optimised out>, self=<optimised out>, nargs=<optimised out>, args=<optimised out>) at src/clingwrapper.cxx:953
#16 0x00007f2e901f5111 in GILCallLL (ctxt=0x7fff2e23d6a0, self=<optimised out>, method=<optimised out>) at src/Executors.cxx:74
#17 CPyCppyy::(anonymous namespace)::ULongExecutor::Execute (this=<optimised out>, method=<optimised out>, self=<optimised out>, ctxt=0x7fff2e23d6a0) at src/Executors.cxx:273
#18 0x00007f2e901aecf9 in CPyCppyy::CPPMethod::ExecuteFast (self=<optimised out>, offset=<optimised out>, ctxt=0x7fff2e23d6a0, this=<optimised out>, this=<optimised out>) at src/CPPMethod.cxx:123
#19 0x00007f2e901b06c9 in CPyCppyy::CPPMethod::Execute (this=this
entry=0x5617908d73a0, self=self
entry=0x0, offset=offset
entry=0, ctxt=ctxt
entry=0x7fff2e23d6a0) at src/CPPMethod.cxx:892
#20 0x00007f2e901aac7f in CPyCppyy::CPPFunction::Call (this=0x5617908d73a0, self=
0x7fff2e23d638: 0x0, args=<optimised out>, nargsf=<optimised out>, kwds=<optimised out>, ctxt=0x7fff2e23d6a0) at src/CPPFunction.cxx:90
#21 0x00007f2e901b6441 in CPyCppyy::(anonymous namespace)::mp_vectorcall (pymeth=0x7f2e8fadec80, args=0x7f2e8fdeaee8, nargsf=9223372036854775811, kwds=0x0) at src/CPPOverload.cxx:641
#22 0x000056178ca25a72 in _PyEval_EvalFrameDefault ()
#23 0x000056178ca373ac in _PyFunction_Vectorcall ()
#24 0x000056178ca20005 in _PyEval_EvalFrameDefault ()
#25 0x000056178ca1c766 in ?? ()
#26 0x000056178cb14456 in PyEval_EvalCode ()
#27 0x000056178cb40f08 in ?? ()
#28 0x000056178cb39d5b in ?? ()
#29 0x000056178cb40c55 in ?? ()
#30 0x000056178cb40138 in _PyRun_SimpleFileObject ()
#31 0x000056178cb3fe33 in _PyRun_AnyFileObject ()
#32 0x000056178cb310ae in Py_RunMain ()
#33 0x000056178cb0734d in Py_BytesMain ()
#34 0x00007f2e97aa3d90 in __libc_start_call_main (main=main
entry=0x56178cb07310, argc=argc
entry=2, argv=argv
entry=0x7fff2e23dfe8) at ../sysdeps/nptl/libc_start_call_main.h:58
#35 0x00007f2e97aa3e40 in __libc_start_main_impl (main=0x56178cb07310, argc=2, argv=0x7fff2e23dfe8, init=<optimised out>, fini=<optimised out>, rtld_fini=<optimised out>, stack_end=0x7fff2e23dfd8) at ../csu/libc-start.c:392
#36 0x000056178cb07245 in _start ()
Process finished with exit code 129 (interrupted by signal 1: SIGHUP)
That segfault is inside another function that is called by the C++ function that you're calling:
#8 0x00007f2e8ec01f71 in CComPortUsb::ReadDeviceIf0(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#9 0x00007f2e8ec01ad7 in CComPortUsb::GetPrinterStatus(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
#10 0x00007f2e8ec01763 in GetPrinterStatus(unsigned char*, unsigned long, unsigned long*) () from /home/james/work/ckp80111/./libCeSmLm.so
I'm not excluding (yet) that there's a problem with the argument conversion, given that all 3 functions have the same arguments, and are thus most likely simply passed through.
However, my first guess is that the 3rd argument isn't allowed to be nullptr
, as used here:
dw_read = 0
result = printer.GetPrinterStatus(recv_buffer, dw_size, dw_read)
Point being that your original example passed a pointer to a null value, not a nullptr:
unsigned long dwRead = 0;
dwResult = GetPrinterStatus(buffer, READ_BUFFER_SIZE, &dwRead);
This is again a problem with these low level functions not exposing exactly what you intend, but also that a Python int
can not be an outparam, so the best automatic guess here is that the intended conversion was to nullptr
. Instead, use ctypes
again:
dwread = ctypes.c_ulong(0)
result = printer.GetPrinterStatus(recv_buffer, dw_size, dw_read)
where this time to intention is clear: if you go through the trouble of creating a ctypes
parameter, it's virtually certain intended to be an outparam, so the conversion to a pointer type is automatic. Alternatively, you can explicitly use ctypes.pointer(dw_read))
if you prefer that for readability.
That did the trick thank you very much for your help @wlav
Hello,
I have been reading through the docs for the past few hours and cannot seem to get types aligned to make the following function call. The call to
GetLibVers()
andopenUSBDevice
are working fineI get the following error
I don't think this is a butg as such just myself struggling with aligning the types. Does anyone have any ideas? I only have the SO and header file for the library
Header File
Working example in C