From: Alexey S. <al...@as...> - 2012-08-15 16:46:29
|
15.08.2012 21:13, William S Fulton пишет: > On 26/07/12 18:20, Alexey Sokolov wrote: >> Hello. >> >> I tried to wrap std::set<MyClass> with -py3 and using pyabc.i >> I did %template(SMyClass) std::set<MyClass>; >> >> But when using it from python the program segfaults. >> >> After hours of debugging I added some output to >> SWIG_Python_NewShadowInstance (python_show_error.patch), which helped me >> to understand the reason of the problem: "TypeError: Can't instantiate >> abstract class SMyClass with abstract methods add, discard", and it >> segfaulted because the python function call returned NULL (which means >> an exception). >> >> So the patch python_abc_set.patch adds these 2 methods to set. >> >> Perhaps it would be good to add the same debug output to other #if >> branches of SWIG_Python_NewShadowInstance as well, for other python >> versions, to help against similar bugs in the future. >> > Alexey, what is the code you are using? I can't get a seg fault, > although I can see a problem there as 'inst' is used without checking > and that needs fixing, but I can't get the code to segfault as it > errors out way before getting there. My simple testcase is: > > > // example.i > %module example > > %include <pyabc.i> > %include <std_set.i> > > %inline %{ > struct MyClass { > bool operator<(const MyClass& other) const { return false; } > }; > %} > %template(SMyClass) std::set<MyClass>; > > > swig -python -py3 -c++ example.i > > and running python code: > > > import example > s = example.SMyClass() > > > Traceback (most recent call last): > File "runme3.py", line 10, in <module> > s = example.SMyClass() > TypeError: Can't instantiate abstract class SMyClass with abstract > methods add, discard > > I have python 3.1.2. > > William I'm embedding python to ZNC using SWIG. (Improving actually, as it already works) The instance of std::set is created from C++ side, and is exposed to python using SWIG_NewInstanceObj. Here're few lines around it: void CPyModule::OnGetAvailableMods(std::set<CModInfo>& ssMods, CModInfo::EModuleType eType) { PyObject* pyName = Py_BuildValue("s", "OnGetAvailableMods"); if (!pyName) { ............. return ; } PyObject* pyArg_ssMods = SWIG_NewInstanceObj(const_cast<std::set<CModInfo>*>(&ssMods), SWIG_TypeQuery("std::set<CModInfo>*"), 0); //// if (!pyArg_ssMods) { CString sPyErr = m_pModPython->GetPyExceptionStr(); ....................... Py_CLEAR(pyName); return ; } ........... } Inside SWIG_NewInstanceObj it crashes. You can see it in action in last git version of ZNC (https://github.com/znc/znc). *After* doing "./configure --enable-python" (but before "make && make install") remove ./swig_lib/python/std_set.i, because ./configure checks that add/discard methods are presented in the generated by SWIG files. Also put attached pyglobal.py to modules/ before running make && make install, it's a simple python ZNC module, which triggers the bug (it's a global ZNC module, and OnGetAvailableMods is called only for global modules) With modpython and this module loaded into ZNC do "/msg *status listavailmods" or go to webadmin to "Your settings" page. To make initial configuration of ZNC run "znc --makeconf". To load these modules you can use "/msg *status loadmod modpython", then "/msg *status loadmod pyglobal" (or via webadmin). Then "/msg *status saveconfig" to tell ZNC to load them automatically on startup, if you don't want to load them each time manually this way during tests. The copied code is from modules/modpython/functions.cpp, which is generated during "make" from modules/modpython/functions.in using modules/modpython/codegen.pl -- Best regards, Alexey "DarthGandalf" Sokolov |