Thread: [pygccxml-development] problem with an array of pointers
Brought to you by:
mbaas,
roman_yakovenko
From: Gordon W. <gor...@gm...> - 2008-07-07 07:27:59
|
Disclaimer: I have no idea what I'm doing and C++ is not one of my strong skills. I'm having a problem with py++, boost, msvc and a third party library I need to bridge to python. I would greatly appreciate any help I can get with this. I don't have the various version information handy but I downloaded all of the boost/py++/msvc stuff from the relevant websites last week. After I installed everything I made it compile and run the quick start example correctly. I ran the library header through the py++ gui, grabbed the py++ code that generated, put it in a .py file, ran that and then copied the resulting files into the quick start example. The header for the library includes this snippet (details obscured to protect the guilty): class bob { public: double *fred[4]; Which produced these snippets in bindings.cpp struct bob_wrapper : bob, bp::wrapper< bob > { <snip> static pyplusplus::containers::static_sized::array_1_t< double *, 4> pyplusplus_fred_wrapper( ::bob & inst ){ return pyplusplus::containers::static_sized::array_1_t< double *, 4>( inst.fred ); } BOOST_PYTHON_MODULE(pyplusplus){ { //::bob <snip> pyplusplus::containers::static_sized::register_array_1< double *, 4, bp::return_internal_reference< > >( "__array_1_double__ptr__4" ); { //bob::fred [variable], type=double *[4] typedef pyplusplus::containers::static_sized::array_1_t< double *, 4> ( *array_wrapper_creator )( ::bob & ); bob_exposer.add_property( "fred" , bp::make_function( array_wrapper_creator(&bob_wrapper::pyplusplus_fred_wrapper) , bp::with_custodian_and_ward_postcall< 0, 1 >() ) ); } which seem to be responsible for this mess C:\PROGRA~1\boost\BOOST_~1\libs\python\example\QUICKS~1>bjam.exe --toolset=msvc warning: Graph library does not contain optional GraphML reader. note: to enable GraphML support, set EXPAT_INCLUDE and EXPAT_LIBPATH to the note: directories containing the Expat headers and libraries, respectively. warning: skipping optional Message Passing Interface (MPI) library. note: to enable MPI support, add "using mpi ;" to user-config.jam. note: to suppress this message, pass "--without-mpi" to bjam. note: otherwise, you can safely ignore this message. Building Boost.Regex with the optional Unicode/ICU support disabled. Please refer to the Boost.Regex documentation for more information (don't panic: this is a strictly optional feature). ...patience... ...found 1193 targets... ...updating 3 targets... compile-c-c++ bin\msvc-9.0express\debug\threading-multi\extending.obj extending.cpp C:\PROGRA~1\boost\BOOST_~1\boost/python/detail/unwind_type.hpp(165) : error C2664: 'boost::python::converter::detail::unwind_type_id_helper::result_ty pe boost::python::detail::unwind_helper2<1>::execute<Generator,double>(U *(__cdecl *)(void),Generator *)' : cannot convert parameter 1 from 'double *c onst (__cdecl *)(void)' to 'double *(__cdecl *)(void)' with [ Generator=boost::python::converter::detail::unwind_type_id_helper, U=double ] This conversion requires a reinterpret_cast, a C-style cast or function-style cast C:\PROGRA~1\boost\BOOST_~1\boost/python/converter/pytype_function.hpp(45) : see reference to function template instantiation 'boost::python::c onverter::detail::unwind_type_id_helper::result_type boost::python::detail::unwind_type<boost::python::converter::detail::unwind_type_id_helper,T>(boo st::type<T> *,Generator *)' being compiled with [ T=double *const , Generator=boost::python::converter::detail::unwind_type_id_helper ] C:\PROGRA~1\boost\BOOST_~1\boost/python/converter/pytype_function.hpp(67) : see reference to function template instantiation 'boost::python::t ype_info boost::python::converter::detail::unwind_type_id_<T>(boost::type<T> *,boost::mpl::false_ *)' being compiled with [ T=double *const ] C:\PROGRA~1\boost\BOOST_~1\boost/python/converter/pytype_function.hpp(65) : while compiling class template member function 'const PyTypeObject *boost::python::converter::expected_pytype_for_arg<T>::get_pytype(void)' with [ T=double *const ] C:\PROGRA~1\boost\BOOST_~1\boost/preprocessor/iteration/detail/local.hpp(34) : see reference to class template instantiation 'boost::python::c onverter::expected_pytype_for_arg<T>' being compiled with [ T=double *const ] C:\PROGRA~1\boost\BOOST_~1\boost/python/detail/signature.hpp(76) : while compiling class template member function 'const boost::python::detail ::signature_element *boost::python::detail::signature_arity<2>::im pl<Sig>::elements(void)' with [ Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/detail/signature.hpp(58) : see reference to class template instantiation 'boost::python::detail::signa ture_arity<2>::impl<Sig>' being compiled with [ Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/detail/caller.hpp(232) : see reference to class template instantiation 'boost::python::detail::signatu re<Sig>' being compiled with [ Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/detail/caller.hpp(231) : while compiling class template member function 'boost::python::detail::py_fun c_sig_info boost::python::detail::caller_arity<2>::im pl<F,Policies,Sig>::signature(void)' with [ F=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, Policies=boost::python::return_internal_reference<>, Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/detail/caller.hpp(169) : see reference to class template instantiation 'boost::python::detail::caller_ arity<2>::impl<F,Policies,Sig>' being compiled with [ F=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, Policies=boost::python::return_internal_reference<>, Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/make_function.hpp(61) : see reference to class template instantiation 'boost::python::detail::caller<F ,CallPolicies,Sig>' being compiled with [ F=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, CallPolicies=boost::python::return_internal_reference<>, Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/make_function.hpp(146) : see reference to function template instantiation 'boost::python::api::object boost::python::detail::make_function_aux<F,CallPolicies,Signature,boost::mpl::int_<N>>(F,const CallPolicies &,const Sig &,const boost::python::detail: :keyword_range &,NumKeywords)' being compiled with [ F=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, CallPolicies=boost::python::return_internal_reference<>, Signature=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long>, N=1, Sig=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long>, NumKeywords=boost::mpl::int_<1> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/class.hpp(544) : see reference to function template instantiation 'boost::python::api::object boost::p ython::make_function<Fn,T2,T1,boost::mpl::vector3<T0,pyplusplus::containers::static_sized::array_1_t<TItemType,size> &,unsigned long>>(F,const CallPol icies &,const Keywords &,const Signature &)' being compiled with [ Fn=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, T2=boost::python::return_internal_reference<>, T1=boost::python::detail::keywords<1>, T0=double *const , TItemType=double *, size=4, F=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, CallPolicies=boost::python::return_internal_reference<>, Keywords=boost::python::detail::keywords<1>, Signature=boost::mpl::vector3<double *const ,pyplusplus::containers::static_sized::array_1_t<double *,4> &,unsigned long> ] C:\PROGRA~1\boost\BOOST_~1\boost/python/class.hpp(259) : see reference to function template instantiation 'void boost::python::class_<W>::def_ impl<pyplusplus::containers::static_sized::array_1_t<TItemType,size>,Fn,boost::python::detail::def_helper<T1,T2>>(T *,const char *,Fn,const Helper &,. ..)' being compiled with [ W=wrapper_t, TItemType=double *, size=4, Fn=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, T1=boost::python::detail::keywords<1>, T2=boost::python::return_internal_reference<>, T=pyplusplus::containers::static_sized::array_1_t<double *,4>, Helper=boost::python::detail::def_helper<boost::python::detail::keywords<1>,boost::python::return_internal_reference<>> ] c:\program files\boost\boost_1_35_0\libs\python\example\quickstart\__array_1.pypp.hpp(164) : see reference to function template instantiation 'boost::python::class_<W> &boost::python::class_<W>::def<double*const (__thiscall pyplusplus::containers::static_sized::array_1_t<TItemType,size>::* ) (unsigned long) const,boost::python::detail::keywords<1>,boost::python::return_internal_reference<>>(const char *,Fn,const A1 &,const A2 &)' being com piled with [ W=wrapper_t, TItemType=double *, size=4, Fn=double *const (__thiscall pyplusplus::containers::static_sized::array_1_t<double *,4>::* )(unsigned long) const, A1=boost::python::detail::keywords<1>, A2=boost::python::return_internal_reference<> ] c:\program files\boost\boost_1_35_0\libs\python\example\quickstart\__array_1.pypp.hpp(157) : while compiling class template member function 'p yplusplus::containers::static_sized::register_array_1<TItemType,size,CallPolicies>::register_array_1(const char *)' with [ TItemType=double *, size=4, CallPolicies=boost::python::return_internal_reference<> ] extending.cpp(100) : see reference to class template instantiation 'pyplusplus::containers::static_sized::register_array_1<TItemType,size,Call Policies>' being compiled with [ TItemType=double *, size=4, CallPolicies=boost::python::return_internal_reference<> ] call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 >nul cl /Zm800 -nologo @"bin\msvc-9.0express\debug\threading-multi\extending.obj.rsp" ...failed compile-c-c++ bin\msvc-9.0express\debug\threading-multi\extending.obj... ...removing bin\msvc-9.0express\debug\threading-multi\extending.obj ...skipped <pbin\msvc-9.0express\debug\threading-multi>extending.pyd for lack of <pbin\msvc-9.0express\debug\threading-multi>extending.obj... ...skipped <pbin\msvc-9.0express\debug\threading-multi>extending.lib for lack of <pbin\msvc-9.0express\debug\threading-multi>extending.obj... ...failed updating 1 target... ...skipped 2 targets... The C++ code involved in most of that template stuff is well beyond my understanding and after a half day of digging through it I have no idea what is going wrong. |
From: Roman Y. <rom...@gm...> - 2008-07-07 08:50:58
|
On Mon, Jul 7, 2008 at 10:28 AM, Gordon Wrigley <gor...@gm...> wrote: > Disclaimer: I have no idea what I'm doing and C++ is not one of my strong > skills. I'm having a problem with py++, boost, msvc and a third party > library I need to bridge to python. I would greatly appreciate any help I > can get with this. :-) > I don't have the various version information handy but I downloaded all of > the boost/py++/msvc stuff from the relevant websites last week. After I > installed everything I made it compile and run the quick start example > correctly. > > I ran the library header through the py++ gui, grabbed the py++ code that > generated, put it in a .py file, ran that and then copied the resulting > files into the quick start example. > > The header for the library includes this snippet (details obscured to > protect the guilty): > > class bob > { > public: > double *fred[4]; This is a bug in Py++. The code generated for "double* fred[4]" caused the compilation error. It is not possible to generate code for "fred" without knowing additional details. In this case Py++ has to exclude this variable from being exposed and give some warning. Now, how can you improve the situation: * exclude variable by your own * take a look on "return_range" ( http://language-binding.net/pyplusplus/documentation/functions/call_policies.html#return-range ) call policies. HTH -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Gordon W. <gor...@gm...> - 2008-07-08 01:30:54
|
OK, that seems to make some sense, but leads to a few lil feature requests. First the py++ code on that page is overly verbose, it would be nice if this could be handled in one line. So for this C++ code: class tom { public: double *data; double dataLen; you might have something like: mb.class_( "tom" ).variable( "data" ).size("tom.dataLen") I realise it's probably not going to be quite that simple, I'm just trying to convey the direction of the idea. Also if you had a standard policy of always having a xLen variable for every x pointer variable (or xLen function for every function returning a pointer) then it'd be nice to be able to capture that in a single line. And of course this would all have to be extended somehow to work with my array of pointers example and the documentations width*heigh example. Also that warning that py++ should give when it runs into one of these should include an example of the sort of line required to fix it. :) Gordon. On Mon, Jul 7, 2008 at 6:51 PM, Roman Yakovenko <rom...@gm...> wrote: > On Mon, Jul 7, 2008 at 10:28 AM, Gordon Wrigley > <gor...@gm...> wrote: > > Disclaimer: I have no idea what I'm doing and C++ is not one of my strong > > skills. I'm having a problem with py++, boost, msvc and a third party > > library I need to bridge to python. I would greatly appreciate any help I > > can get with this. > > :-) > > > I don't have the various version information handy but I downloaded all > of > > the boost/py++/msvc stuff from the relevant websites last week. After I > > installed everything I made it compile and run the quick start example > > correctly. > > > > I ran the library header through the py++ gui, grabbed the py++ code that > > generated, put it in a .py file, ran that and then copied the resulting > > files into the quick start example. > > > > The header for the library includes this snippet (details obscured to > > protect the guilty): > > > > class bob > > { > > public: > > double *fred[4]; > > This is a bug in Py++. > > The code generated for "double* fred[4]" caused the compilation error. > It is not possible to generate code for "fred" without knowing > additional details. In this case Py++ has to exclude this variable > from being exposed and give some warning. > > Now, how can you improve the situation: > * exclude variable by your own > * take a look on "return_range" ( > > http://language-binding.net/pyplusplus/documentation/functions/call_policies.html#return-range > ) call policies. > > HTH > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > |
From: Roman Y. <rom...@gm...> - 2008-07-08 05:00:26
|
On Tue, Jul 8, 2008 at 4:31 AM, Gordon Wrigley <gor...@gm...> wrote: > OK, that seems to make some sense, but leads to a few lil feature requests. > > First the py++ code on that page is overly verbose, it would be nice if this > could be handled in one line. So for this C++ code: > > class tom > { > public: > double *data; > double dataLen; > > you might have something like: > > mb.class_( "tom" ).variable( "data" ).size("tom.dataLen") > > I realise it's probably not going to be quite that simple, I'm just trying > to convey the direction of the idea. Interesting idea. I will try it. > Also if you had a standard policy of > always having a xLen variable for every x pointer variable (or xLen function > for every function returning a pointer) then it'd be nice to be able to > capture that in a single line. > > And of course this would all have to be extended somehow to work with my > array of pointers example and the documentations width*heigh example. :-). Adding support for 2 dimensions array is on my todo list. > Also that warning that py++ should give when it runs into one of these > should include an example of the sort of line required to fix it. I will fix it before next release -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Gordon W. <gor...@gm...> - 2008-07-08 01:47:23
|
This is about the size right? If so is it going to complain about every pointer variable I have? and if that is the case then why doesn't it just produce a warning and then assume that if it's not null then the length is 1, that at least will work for regular pointers. Or is this just about the combination of the pointer and the array? On Tue, Jul 8, 2008 at 11:31 AM, Gordon Wrigley <gor...@gm...> wrote: > OK, that seems to make some sense, but leads to a few lil feature requests. > > First the py++ code on that page is overly verbose, it would be nice if > this could be handled in one line. So for this C++ code: > > class tom > { > public: > double *data; > double dataLen; > > you might have something like: > > mb.class_( "tom" ).variable( "data" ).size("tom.dataLen") > > I realise it's probably not going to be quite that simple, I'm just trying > to convey the direction of the idea. Also if you had a standard policy of > always having a xLen variable for every x pointer variable (or xLen function > for every function returning a pointer) then it'd be nice to be able to > capture that in a single line. > > And of course this would all have to be extended somehow to work with my > array of pointers example and the documentations width*heigh example. > > Also that warning that py++ should give when it runs into one of these > should include an example of the sort of line required to fix it. > > :) > > Gordon. > > > On Mon, Jul 7, 2008 at 6:51 PM, Roman Yakovenko <rom...@gm...> > wrote: > >> On Mon, Jul 7, 2008 at 10:28 AM, Gordon Wrigley >> <gor...@gm...> wrote: >> > Disclaimer: I have no idea what I'm doing and C++ is not one of my >> strong >> > skills. I'm having a problem with py++, boost, msvc and a third party >> > library I need to bridge to python. I would greatly appreciate any help >> I >> > can get with this. >> >> :-) >> >> > I don't have the various version information handy but I downloaded all >> of >> > the boost/py++/msvc stuff from the relevant websites last week. After I >> > installed everything I made it compile and run the quick start example >> > correctly. >> > >> > I ran the library header through the py++ gui, grabbed the py++ code >> that >> > generated, put it in a .py file, ran that and then copied the resulting >> > files into the quick start example. >> > >> > The header for the library includes this snippet (details obscured to >> > protect the guilty): >> > >> > class bob >> > { >> > public: >> > double *fred[4]; >> >> This is a bug in Py++. >> >> The code generated for "double* fred[4]" caused the compilation error. >> It is not possible to generate code for "fred" without knowing >> additional details. In this case Py++ has to exclude this variable >> from being exposed and give some warning. >> >> Now, how can you improve the situation: >> * exclude variable by your own >> * take a look on "return_range" ( >> >> http://language-binding.net/pyplusplus/documentation/functions/call_policies.html#return-range >> ) call policies. >> >> HTH >> >> -- >> Roman Yakovenko >> C++ Python language binding >> http://www.language-binding.net/ >> > > |
From: Roman Y. <rom...@gm...> - 2008-07-08 05:02:09
|
On Tue, Jul 8, 2008 at 4:47 AM, Gordon Wrigley <gor...@gm...> wrote: > This is about the size right? If so is it going to complain about every > pointer variable I have? and if that is the case then why doesn't it just > produce a warning and then assume that if it's not null then the length is > 1, that at least will work for regular pointers. > Or is this just about the combination of the pointer and the array? The combination. Py++ treats pretty well "regular" pointers and provides few call policies for convenience: http://language-binding.net/pyplusplus/documentation/functions/call_policies.html#py-defined-call-policies -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Gordon W. <gor...@gm...> - 2008-07-09 11:48:57
|
> May we switch to the mailing list? There a lot of advantages to use it. Sure I just dropped off the mailing list so there wouldn't be so much noise for everyone else. > The important question is: how "pythonic" your interface should be? It needs to be quite pythonic, the eventual users aren't programmers by trade and only have exposure to python, no C or C++ abilities, I really can't count on them being careful at all. I'd also like keep it all within the library, where there have to be wrappers I'd rather they were not visible to the end users. > void getName(char *buff, int len){ > strncpy(buff, "bob", len); > } > Hmm. In this case we can create new function transformation > Another solution is to generate wrapper for such functions and to expose it. The best wrapper option I can think of for this is: static boost::python::object getName(const Bob& bob, int len){ char buf[len]; bob.getName(buf, len); std::string hw2(buf); return bp::object( hw2 ); } And then I guess I do this stuff http://language-binding.net/pyplusplus/documentation/how_to/how_to.html in py++ which all seems straight forward, unfortunately I can't test it until I get to work tomorrow. I'm not sure if this would be useful enough for other people to justify turning it into a transform. >> The planet example seems to work fine (you suggested in another mail that it >> might). > Good Sorry, my mistake I haven't actually tested the planet example, what I have tested is reading a char array, and that works. However when the the char array contains a nul terminated string the interface is somewhat ugly so I'm considering wrapping those, but that's a problem for later. I will check the planet example in the morning but I suspect at this stage it's just not being exported at all, I know for sure that char* variables aren't showing up at all in the generated cpp file. > char *fred; > Consider my advice about ctypes. > I can patch Py++ today, so instead of exposing the variable it will > expose the variable address: Thank you but I think I'd rather avoid that. I think can see now how I could produce and tie in get_fred and set_fred functions and how not to leak memory while doing it, I will give that a go tomorrow and we'll see how it works out. What I would like to do that I can't currently see a way of achieving is to wrap those get and set functions together into something that looks like a variable so on the python side instead of going bob.set_fred("hello") print bob.get_fred() I can use it like this instead bob.fred="hello" print bob.fred This is a nice to have as it means I don't have to deviate as much from the C++ api and once this is all going I'm going to have to document everywhere where I deviate from that api. >> I haven't tested the loadFile example yet and I consider it low priority. > I guess "modify_type" function transformation could be used. It is a little bit ugly but it will work It may already be working, like I said I haven't tried it yet, however it is showing up in the generated cpp file so maybe it's all good. On Wed, Jul 9, 2008 at 7:01 PM, Roman Yakovenko <rom...@gm...> wrote: > On Wed, Jul 9, 2008 at 10:43 AM, Gordon Wrigley > <gor...@gm...> wrote: > > Ok, the disclaimers again, I'm not an expert at either C++ or Python but > I > > can get by in both, I don't generally use windows and I haven't done any > > development for or on windows in years and I've never used boost or msvc > > before. > > May we switch to the mailing list? There a lot of advantages to use it. > > > My work has recently acquired a moderately large and expensive piece of > test > > equipment. This device has a bunch of windows dlls with C++ headers for > > developing automation tools. These headers total several thousand lines. > > I've been given the job of making it work from Python which is our > > automation language of choice. I got the job because I have an > established > > history of being able to slove problems. > > > > Currently I have a py++ script that gets most of the stuff exported but > it's > > hard to say how much is exported correctly. Currently the script produces > > ~170 lines of warnings and I understand them all (this is a big step up > from > > yesterday). I've gotten the bjam stuff sorted and I can compile link all > the > > various dlls (it also uses the matlab common runtime). Then from the > python > > console I can import the lib (that was a big step all the dll's have to > be > > in line for that to work) run the initilization stuff and connect to the > > device, or at least I appear to connect I haven't been able to do > anything > > useful with it yet. > > I understand your warnings and lack of confidence. I tried to build Py++ in > a > such way, that if it exports thing they work, otherwise there is a warning > or > the declaration is not exported. > > > Alot of the stuff in the headers is very basic C like, so char*'s instead > of > > strings, arrays of pointers, pointer passing etc and very little in the > way > > of OO design or C++ style memory management, actually there's very little > > dynamic memory stuff at all. > > > > I realise that to get a lot of it going I will need to do make custom > > handlers and that's ok, once I have the first couple of those going I > should > > be able to figure the rest out quite quickly. > > > > As an example of some of the stuff I need, in the following C++ code > (which > > should compile and run with a couple of warnings) I need to be able to do > > all the stuff in the main function from python. > > The important question is: how "pythonic" your interface should be? > I will explain: in almost no time, you can generate code that returns the > address of the variable, than you can use ctypes built-in module to work > with > that variable. Take a look on > http://python.net/crew/theller/ctypes/reference.html#data-types > "from_address" function. > > Of course your users will have to be very very careful. > > You can improve and to create small wrappers around classes in Python > that checks preconditions. > > Another approach is to expose "Pythonic" API, but it has its price and > this is not cheep. I suggest you to go > with the first one. > > > #include <iostream> > > > > class Bob{ > > public: > > char *fred; > > char *planet; > > double image[10]; > > double *data[2]; > > > > Bob(){ > > planet="Naboo"; > > > > for(int i=0; i<10; i++) image[i]=i; > > > > data[0] = new double[5]; > > data[1] = new double[5]; > > for(int i=0; i<5; i++){ > > data[0][i] = 5-i; > > data[1][i] = i+5; > > } > > } > > > > void getName(char *buff, int len){ > > strncpy(buff, "bob", len); > > } > > > > int loadFile(char *name){ > > // do stuff > > return 0; > > } > > }; > > > > int main(int argc, char **argv){ > > Bob *bob = new Bob(); > > std::cout << "bob->planet = " << bob->planet << std::endl; > > > > bob->fred = "ABC"; > > std::cout << "bob->fred = " << bob->fred << std::endl; > > > > char buff[10]; > > bob->getName(buff, 10); > > std::cout << "buff = " << buff << std::endl; > > > > std::cout << "bob->image[7] = " << bob->image[7] << std::endl; > > > > std::cout << "bob->data[1][2] = " << bob->data[1][2] << std::endl; > > > > std::cout << "bob->loadFile = " << bob->loadFile("data.dat") << > > std::endl; > > } > > > > Getting the getName example above going is probably my most pressing need > as > > I need that to get version and status info off the device in order to > verify > > that I do actually have a valid connection. > > Hmm. In this case we can create new function transformation > ( > http://language-binding.net/pyplusplus/documentation/functions/transformation/transformation.html > ) > > It should not be too difficult. > > Another solution is to generate wrapper for such functions and to expose > it. > > > The planet example seems to work fine (you suggested in another mail that > it > > might). > > Good > > > Once I get the fred example going I can probably figure out the the image > > and data ones. > > Consider my advice about ctypes. > > I can patch Py++ today, so instead of exposing the variable it will > expose the variable address: > > mb = module_builder_t( ... ) > mb.var( 'fred' ).expose_address = True > > Better name for property is welcome > > > I haven't tested the loadFile example yet and I consider it low priority. > > I guess "modify_type" function transformation could be used. It is a > little bit ugly > but it will work > > > Also I very much appreciate the help you have been giving me, thank you. > > My pleasure. > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > |
From: Gordon W. <gor...@gm...> - 2008-07-10 00:06:36
|
on http://language-binding.net/pyplusplus/documentation/how_to/how_to.html I believe the following code: registration_code = 'def( "get_size", &%s::get_size )' % window.wrapper_alias mb = module_builder_t( ... ) window = mb.class_( "window_t" ) window.member_function( "get_size" ).exclude() window.add_wrapper_code( wrapper_code ) window.registration_code( registration_code ) should instead read mb = module_builder_t( ... ) window = mb.class_( "window_t" ) window.member_function( "get_size" ).exclude() window.add_wrapper_code( wrapper_code ) registration_code = 'def( "get_size", &%s::get_size )' % window.wrapper_alias window.add_registration_code( registration_code ) and I now have the getName example working On Wed, Jul 9, 2008 at 9:49 PM, Gordon Wrigley <gor...@gm...> wrote: > > May we switch to the mailing list? There a lot of advantages to use it. > > Sure I just dropped off the mailing list so there wouldn't be so much noise > for everyone else. > > > The important question is: how "pythonic" your interface should be? > > It needs to be quite pythonic, the eventual users aren't programmers by > trade and only have exposure to python, no C or C++ abilities, I really > can't count on them being careful at all. > I'd also like keep it all within the library, where there have to be > wrappers I'd rather they were not visible to the end users. > > > void getName(char *buff, int len){ > > strncpy(buff, "bob", len); > > } > > Hmm. In this case we can create new function transformation > > Another solution is to generate wrapper for such functions and to expose > it. > > The best wrapper option I can think of for this is: > static boost::python::object getName(const Bob& bob, int len){ > char buf[len]; > bob.getName(buf, len); > std::string hw2(buf); > return bp::object( hw2 ); > } > And then I guess I do this stuff > http://language-binding.net/pyplusplus/documentation/how_to/how_to.html in > py++ which all seems straight forward, unfortunately I can't test it until I > get to work tomorrow. > I'm not sure if this would be useful enough for other people to justify > turning it into a transform. > > >> The planet example seems to work fine (you suggested in another mail > that it > >> might). > > Good > > Sorry, my mistake I haven't actually tested the planet example, what I have > tested is reading a char array, and that works. > However when the the char array contains a nul terminated string the > interface is somewhat ugly so I'm considering wrapping those, but that's a > problem for later. > I will check the planet example in the morning but I suspect at this stage > it's just not being exported at all, I know for sure that char* variables > aren't showing up at all in the generated cpp file. > > > char *fred; > > Consider my advice about ctypes. > > I can patch Py++ today, so instead of exposing the variable it will > > expose the variable address: > > Thank you but I think I'd rather avoid that. > I think can see now how I could produce and tie in get_fred and set_fred > functions and how not to leak memory while doing it, I will give that a go > tomorrow and we'll see how it works out. > What I would like to do that I can't currently see a way of achieving is to > wrap those get and set functions together into something that looks like a > variable so on the python side instead of going > bob.set_fred("hello") > print bob.get_fred() > I can use it like this instead > bob.fred="hello" > print bob.fred > This is a nice to have as it means I don't have to deviate as much from the > C++ api and once this is all going I'm going to have to document everywhere > where I deviate from that api. > > >> I haven't tested the loadFile example yet and I consider it low > priority. > > I guess "modify_type" function transformation could be used. It is a > little bit ugly but it will work > > It may already be working, like I said I haven't tried it yet, however it > is showing up in the generated cpp file so maybe it's all good. > > > On Wed, Jul 9, 2008 at 7:01 PM, Roman Yakovenko <rom...@gm...> > wrote: > >> On Wed, Jul 9, 2008 at 10:43 AM, Gordon Wrigley >> <gor...@gm...> wrote: >> > Ok, the disclaimers again, I'm not an expert at either C++ or Python but >> I >> > can get by in both, I don't generally use windows and I haven't done any >> > development for or on windows in years and I've never used boost or msvc >> > before. >> >> May we switch to the mailing list? There a lot of advantages to use it. >> >> > My work has recently acquired a moderately large and expensive piece of >> test >> > equipment. This device has a bunch of windows dlls with C++ headers for >> > developing automation tools. These headers total several thousand lines. >> > I've been given the job of making it work from Python which is our >> > automation language of choice. I got the job because I have an >> established >> > history of being able to slove problems. >> > >> > Currently I have a py++ script that gets most of the stuff exported but >> it's >> > hard to say how much is exported correctly. Currently the script >> produces >> > ~170 lines of warnings and I understand them all (this is a big step up >> from >> > yesterday). I've gotten the bjam stuff sorted and I can compile link all >> the >> > various dlls (it also uses the matlab common runtime). Then from the >> python >> > console I can import the lib (that was a big step all the dll's have to >> be >> > in line for that to work) run the initilization stuff and connect to the >> > device, or at least I appear to connect I haven't been able to do >> anything >> > useful with it yet. >> >> I understand your warnings and lack of confidence. I tried to build Py++ >> in a >> such way, that if it exports thing they work, otherwise there is a warning >> or >> the declaration is not exported. >> >> > Alot of the stuff in the headers is very basic C like, so char*'s >> instead of >> > strings, arrays of pointers, pointer passing etc and very little in the >> way >> > of OO design or C++ style memory management, actually there's very >> little >> > dynamic memory stuff at all. >> > >> > I realise that to get a lot of it going I will need to do make custom >> > handlers and that's ok, once I have the first couple of those going I >> should >> > be able to figure the rest out quite quickly. >> > >> > As an example of some of the stuff I need, in the following C++ code >> (which >> > should compile and run with a couple of warnings) I need to be able to >> do >> > all the stuff in the main function from python. >> >> The important question is: how "pythonic" your interface should be? >> I will explain: in almost no time, you can generate code that returns the >> address of the variable, than you can use ctypes built-in module to work >> with >> that variable. Take a look on >> http://python.net/crew/theller/ctypes/reference.html#data-types >> "from_address" function. >> >> Of course your users will have to be very very careful. >> >> You can improve and to create small wrappers around classes in Python >> that checks preconditions. >> >> Another approach is to expose "Pythonic" API, but it has its price and >> this is not cheep. I suggest you to go >> with the first one. >> >> > #include <iostream> >> > >> > class Bob{ >> > public: >> > char *fred; >> > char *planet; >> > double image[10]; >> > double *data[2]; >> > >> > Bob(){ >> > planet="Naboo"; >> > >> > for(int i=0; i<10; i++) image[i]=i; >> > >> > data[0] = new double[5]; >> > data[1] = new double[5]; >> > for(int i=0; i<5; i++){ >> > data[0][i] = 5-i; >> > data[1][i] = i+5; >> > } >> > } >> > >> > void getName(char *buff, int len){ >> > strncpy(buff, "bob", len); >> > } >> > >> > int loadFile(char *name){ >> > // do stuff >> > return 0; >> > } >> > }; >> > >> > int main(int argc, char **argv){ >> > Bob *bob = new Bob(); >> > std::cout << "bob->planet = " << bob->planet << std::endl; >> > >> > bob->fred = "ABC"; >> > std::cout << "bob->fred = " << bob->fred << std::endl; >> > >> > char buff[10]; >> > bob->getName(buff, 10); >> > std::cout << "buff = " << buff << std::endl; >> > >> > std::cout << "bob->image[7] = " << bob->image[7] << std::endl; >> > >> > std::cout << "bob->data[1][2] = " << bob->data[1][2] << std::endl; >> > >> > std::cout << "bob->loadFile = " << bob->loadFile("data.dat") << >> > std::endl; >> > } >> > >> > Getting the getName example above going is probably my most pressing >> need as >> > I need that to get version and status info off the device in order to >> verify >> > that I do actually have a valid connection. >> >> Hmm. In this case we can create new function transformation >> ( >> http://language-binding.net/pyplusplus/documentation/functions/transformation/transformation.html >> ) >> >> It should not be too difficult. >> >> Another solution is to generate wrapper for such functions and to expose >> it. >> >> > The planet example seems to work fine (you suggested in another mail >> that it >> > might). >> >> Good >> >> > Once I get the fred example going I can probably figure out the the >> image >> > and data ones. >> >> Consider my advice about ctypes. >> >> I can patch Py++ today, so instead of exposing the variable it will >> expose the variable address: >> >> mb = module_builder_t( ... ) >> mb.var( 'fred' ).expose_address = True >> >> Better name for property is welcome >> >> > I haven't tested the loadFile example yet and I consider it low >> priority. >> >> I guess "modify_type" function transformation could be used. It is a >> little bit ugly >> but it will work >> >> > Also I very much appreciate the help you have been giving me, thank you. >> >> My pleasure. >> >> -- >> Roman Yakovenko >> C++ Python language binding >> http://www.language-binding.net/ >> > > |
From: Gordon W. <gor...@gm...> - 2008-07-10 05:07:28
|
With regard to http://www.language-binding.net/pyplusplus/documentation/apidocs/pyplusplus.module_builder.builder.module_builder_t-class.html Is there a document that explains exactly what the different methods (ie vars, calldefs, mem_funs, decls, etc, etc) correspond to, some of them, like vars for example are reasonably obvious, but others like call_defs are not as obvious. On Thu, Jul 10, 2008 at 10:06 AM, Gordon Wrigley <gor...@gm...> wrote: > on http://language-binding.net/pyplusplus/documentation/how_to/how_to.htmlI believe the following code: > > registration_code = 'def( "get_size", &%s::get_size )' % > window.wrapper_alias > > mb = module_builder_t( ... ) > window = mb.class_( "window_t" ) > window.member_function( "get_size" ).exclude() > window.add_wrapper_code( wrapper_code ) > window.registration_code( registration_code ) > > should instead read > > mb = module_builder_t( ... ) > window = mb.class_( "window_t" ) > window.member_function( "get_size" ).exclude() > window.add_wrapper_code( wrapper_code ) > registration_code = 'def( "get_size", &%s::get_size )' % > window.wrapper_alias > window.add_registration_code( registration_code ) > > and I now have the getName example working > > > > On Wed, Jul 9, 2008 at 9:49 PM, Gordon Wrigley <gor...@gm...> > wrote: > >> > May we switch to the mailing list? There a lot of advantages to use it. >> >> Sure I just dropped off the mailing list so there wouldn't be so much >> noise for everyone else. >> >> > The important question is: how "pythonic" your interface should be? >> >> It needs to be quite pythonic, the eventual users aren't programmers by >> trade and only have exposure to python, no C or C++ abilities, I really >> can't count on them being careful at all. >> I'd also like keep it all within the library, where there have to be >> wrappers I'd rather they were not visible to the end users. >> >> > void getName(char *buff, int len){ >> > strncpy(buff, "bob", len); >> > } >> > Hmm. In this case we can create new function transformation >> > Another solution is to generate wrapper for such functions and to expose >> it. >> >> The best wrapper option I can think of for this is: >> static boost::python::object getName(const Bob& bob, int len){ >> char buf[len]; >> bob.getName(buf, len); >> std::string hw2(buf); >> return bp::object( hw2 ); >> } >> And then I guess I do this stuff >> http://language-binding.net/pyplusplus/documentation/how_to/how_to.htmlin py++ which all seems straight forward, unfortunately I can't test it >> until I get to work tomorrow. >> I'm not sure if this would be useful enough for other people to justify >> turning it into a transform. >> >> >> The planet example seems to work fine (you suggested in another mail >> that it >> >> might). >> > Good >> >> Sorry, my mistake I haven't actually tested the planet example, what I >> have tested is reading a char array, and that works. >> However when the the char array contains a nul terminated string the >> interface is somewhat ugly so I'm considering wrapping those, but that's a >> problem for later. >> I will check the planet example in the morning but I suspect at this stage >> it's just not being exported at all, I know for sure that char* variables >> aren't showing up at all in the generated cpp file. >> >> > char *fred; >> > Consider my advice about ctypes. >> > I can patch Py++ today, so instead of exposing the variable it will >> > expose the variable address: >> >> Thank you but I think I'd rather avoid that. >> I think can see now how I could produce and tie in get_fred and set_fred >> functions and how not to leak memory while doing it, I will give that a go >> tomorrow and we'll see how it works out. >> What I would like to do that I can't currently see a way of achieving is >> to wrap those get and set functions together into something that looks like >> a variable so on the python side instead of going >> bob.set_fred("hello") >> print bob.get_fred() >> I can use it like this instead >> bob.fred="hello" >> print bob.fred >> This is a nice to have as it means I don't have to deviate as much from >> the C++ api and once this is all going I'm going to have to document >> everywhere where I deviate from that api. >> >> >> I haven't tested the loadFile example yet and I consider it low >> priority. >> > I guess "modify_type" function transformation could be used. It is a >> little bit ugly but it will work >> >> It may already be working, like I said I haven't tried it yet, however it >> is showing up in the generated cpp file so maybe it's all good. >> >> >> On Wed, Jul 9, 2008 at 7:01 PM, Roman Yakovenko < >> rom...@gm...> wrote: >> >>> On Wed, Jul 9, 2008 at 10:43 AM, Gordon Wrigley >>> <gor...@gm...> wrote: >>> > Ok, the disclaimers again, I'm not an expert at either C++ or Python >>> but I >>> > can get by in both, I don't generally use windows and I haven't done >>> any >>> > development for or on windows in years and I've never used boost or >>> msvc >>> > before. >>> >>> May we switch to the mailing list? There a lot of advantages to use it. >>> >>> > My work has recently acquired a moderately large and expensive piece of >>> test >>> > equipment. This device has a bunch of windows dlls with C++ headers for >>> > developing automation tools. These headers total several thousand >>> lines. >>> > I've been given the job of making it work from Python which is our >>> > automation language of choice. I got the job because I have an >>> established >>> > history of being able to slove problems. >>> > >>> > Currently I have a py++ script that gets most of the stuff exported but >>> it's >>> > hard to say how much is exported correctly. Currently the script >>> produces >>> > ~170 lines of warnings and I understand them all (this is a big step up >>> from >>> > yesterday). I've gotten the bjam stuff sorted and I can compile link >>> all the >>> > various dlls (it also uses the matlab common runtime). Then from the >>> python >>> > console I can import the lib (that was a big step all the dll's have to >>> be >>> > in line for that to work) run the initilization stuff and connect to >>> the >>> > device, or at least I appear to connect I haven't been able to do >>> anything >>> > useful with it yet. >>> >>> I understand your warnings and lack of confidence. I tried to build Py++ >>> in a >>> such way, that if it exports thing they work, otherwise there is a >>> warning or >>> the declaration is not exported. >>> >>> > Alot of the stuff in the headers is very basic C like, so char*'s >>> instead of >>> > strings, arrays of pointers, pointer passing etc and very little in the >>> way >>> > of OO design or C++ style memory management, actually there's very >>> little >>> > dynamic memory stuff at all. >>> > >>> > I realise that to get a lot of it going I will need to do make custom >>> > handlers and that's ok, once I have the first couple of those going I >>> should >>> > be able to figure the rest out quite quickly. >>> > >>> > As an example of some of the stuff I need, in the following C++ code >>> (which >>> > should compile and run with a couple of warnings) I need to be able to >>> do >>> > all the stuff in the main function from python. >>> >>> The important question is: how "pythonic" your interface should be? >>> I will explain: in almost no time, you can generate code that returns the >>> address of the variable, than you can use ctypes built-in module to work >>> with >>> that variable. Take a look on >>> http://python.net/crew/theller/ctypes/reference.html#data-types >>> "from_address" function. >>> >>> Of course your users will have to be very very careful. >>> >>> You can improve and to create small wrappers around classes in Python >>> that checks preconditions. >>> >>> Another approach is to expose "Pythonic" API, but it has its price and >>> this is not cheep. I suggest you to go >>> with the first one. >>> >>> > #include <iostream> >>> > >>> > class Bob{ >>> > public: >>> > char *fred; >>> > char *planet; >>> > double image[10]; >>> > double *data[2]; >>> > >>> > Bob(){ >>> > planet="Naboo"; >>> > >>> > for(int i=0; i<10; i++) image[i]=i; >>> > >>> > data[0] = new double[5]; >>> > data[1] = new double[5]; >>> > for(int i=0; i<5; i++){ >>> > data[0][i] = 5-i; >>> > data[1][i] = i+5; >>> > } >>> > } >>> > >>> > void getName(char *buff, int len){ >>> > strncpy(buff, "bob", len); >>> > } >>> > >>> > int loadFile(char *name){ >>> > // do stuff >>> > return 0; >>> > } >>> > }; >>> > >>> > int main(int argc, char **argv){ >>> > Bob *bob = new Bob(); >>> > std::cout << "bob->planet = " << bob->planet << std::endl; >>> > >>> > bob->fred = "ABC"; >>> > std::cout << "bob->fred = " << bob->fred << std::endl; >>> > >>> > char buff[10]; >>> > bob->getName(buff, 10); >>> > std::cout << "buff = " << buff << std::endl; >>> > >>> > std::cout << "bob->image[7] = " << bob->image[7] << std::endl; >>> > >>> > std::cout << "bob->data[1][2] = " << bob->data[1][2] << std::endl; >>> > >>> > std::cout << "bob->loadFile = " << bob->loadFile("data.dat") << >>> > std::endl; >>> > } >>> > >>> > Getting the getName example above going is probably my most pressing >>> need as >>> > I need that to get version and status info off the device in order to >>> verify >>> > that I do actually have a valid connection. >>> >>> Hmm. In this case we can create new function transformation >>> ( >>> http://language-binding.net/pyplusplus/documentation/functions/transformation/transformation.html >>> ) >>> >>> It should not be too difficult. >>> >>> Another solution is to generate wrapper for such functions and to expose >>> it. >>> >>> > The planet example seems to work fine (you suggested in another mail >>> that it >>> > might). >>> >>> Good >>> >>> > Once I get the fred example going I can probably figure out the the >>> image >>> > and data ones. >>> >>> Consider my advice about ctypes. >>> >>> I can patch Py++ today, so instead of exposing the variable it will >>> expose the variable address: >>> >>> mb = module_builder_t( ... ) >>> mb.var( 'fred' ).expose_address = True >>> >>> Better name for property is welcome >>> >>> > I haven't tested the loadFile example yet and I consider it low >>> priority. >>> >>> I guess "modify_type" function transformation could be used. It is a >>> little bit ugly >>> but it will work >>> >>> > Also I very much appreciate the help you have been giving me, thank >>> you. >>> >>> My pleasure. >>> >>> -- >>> Roman Yakovenko >>> C++ Python language binding >>> http://www.language-binding.net/ >>> >> >> > |
From: Roman Y. <rom...@gm...> - 2008-07-10 06:09:48
|
On Thu, Jul 10, 2008 at 8:07 AM, Gordon Wrigley <gor...@gm...> wrote: > With regard to > http://www.language-binding.net/pyplusplus/documentation/apidocs/pyplusplus.module_builder.builder.module_builder_t-class.html > Is there a document that explains exactly what the different methods (ie > vars, calldefs, mem_funs, decls, etc, etc) correspond to, some of them, like > vars for example are reasonably obvious, but others like call_defs are not > as obvious. may be this: http://www.language-binding.net/pygccxml/declarations_uml.png "calldef" is the pygccxml( Py++ ) way to name functions. It is the base class for: constructors, destructors, operators, free and member functions. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Roman Y. <rom...@gm...> - 2008-07-10 06:07:11
|
On Thu, Jul 10, 2008 at 3:06 AM, Gordon Wrigley <gor...@gm...> wrote: > on http://language-binding.net/pyplusplus/documentation/how_to/how_to.html I > believe the following code: > > registration_code = 'def( "get_size", &%s::get_size )' % > window.wrapper_alias > > mb = module_builder_t( ... ) > window = mb.class_( "window_t" ) > window.member_function( "get_size" ).exclude() > window.add_wrapper_code( wrapper_code ) > window.registration_code( registration_code ) > > should instead read > > mb = module_builder_t( ... ) > window = mb.class_( "window_t" ) > window.member_function( "get_size" ).exclude() > window.add_wrapper_code( wrapper_code ) > registration_code = 'def( "get_size", &%s::get_size )' % > window.wrapper_alias > window.add_registration_code( registration_code ) > > and I now have the getName example working This your first contribution to the project :-) Thanks. I fixed it. -- Roman Yakovenko C++ Python language binding http://www.language-binding.net/ |
From: Gordon W. <gor...@gm...> - 2008-07-10 06:23:02
|
On the documentation front, the main thing that was confusing me is that menu in the top left, once I realised that it was the main navigation tool getting around the docs got a lot easier. Also the insight that all those vars, mem_funs etc functions in module_builder_t return further module_builder_t's helped a lot. I'm getting the documentation now and it's helping a lot. With regard to the example... I already mentioned that getName is going. I put the getters and setters in for the fred/planet example and the class properties section of this page http://www.boost.org/doc/libs/1_35_0/libs/python/doc/tutorial/doc/html/python/exposing.htmlthat you sent me earlier (thanks for that) helped me figure out how to tie them in in the way I want, testing that at the moment and it seems to be working. The loadFile example was already working (and I had already tested it in a different context but hadn't realised) Will start into the image and data examples after the current round of testing. All in all today is going very well. On Thu, Jul 10, 2008 at 4:07 PM, Roman Yakovenko <rom...@gm...> wrote: > On Thu, Jul 10, 2008 at 3:06 AM, Gordon Wrigley > <gor...@gm...> wrote: > > on > http://language-binding.net/pyplusplus/documentation/how_to/how_to.html I > > believe the following code: > > > > registration_code = 'def( "get_size", &%s::get_size )' % > > window.wrapper_alias > > > > mb = module_builder_t( ... ) > > window = mb.class_( "window_t" ) > > window.member_function( "get_size" ).exclude() > > window.add_wrapper_code( wrapper_code ) > > window.registration_code( registration_code ) > > > > should instead read > > > > mb = module_builder_t( ... ) > > window = mb.class_( "window_t" ) > > window.member_function( "get_size" ).exclude() > > window.add_wrapper_code( wrapper_code ) > > registration_code = 'def( "get_size", &%s::get_size )' % > > window.wrapper_alias > > window.add_registration_code( registration_code ) > > > > and I now have the getName example working > > This your first contribution to the project :-) > > Thanks. I fixed it. > > > -- > Roman Yakovenko > C++ Python language binding > http://www.language-binding.net/ > |