help with CXX-4.2 and add_keyword_method
I'm trying to use add_keyword_method in the appended code and am getting the following errors from KCC-3.4f under Solaris 5.6. Am I guessing wrong as to the correct synax? Thanks Phil "/home/phil/include/CXX-4.2/CXX_Extensions.h", line 164: error: no instance of constructor "Py::MethodDefExt<T>::MethodDefExt [with T=testkey_module]" matches the argument list argument types are: (const char *, Py::ExtensionModule<testkey_module>::method_keyword_funct ion_t, PyObject *(PyObject *, PyObject *, PyObject *), const char *) name, ^ detected during instantiation of "void Py::ExtensionModule<T>::add_keyword_method(const char *, Py::ExtensionModule<T>::method_keyword_function_t, const char *) [with T=testkey_module]" at line 20 of "testkey.cc" #include "Python.h" #include "CXX_Objects.h" #include "CXX_Extensions.h" #include <algorithm> USING(namespace Py) USING(namespace std) extern "C" void inittestkey(); class testkey_module : public ExtensionModule<testkey_module> { public: testkey_module() : ExtensionModule<testkey_module>( "testkey" ) { add_varargs_method("sum", &testkey_module::ex_sum, "testing"); add_keyword_method("sum2", &testkey_module::ex_sum2, "testing2"); initialize( "documentation for the testkey module" ); Dict d( moduleDictionary() ); d["a_constant"] = Int(12); } virtual ~testkey_module() {} private: Object ex_sum (const Tuple &a) { cout << a[0] << endl; return a[0]; } Object ex_sum2 (const Tuple &a, const Dict &b) { cout << a[1] << endl; return a[1]; } }; void inittestkey() { static testkey_module *testkey = new testkey_module; }
There is a bug in the keyword template. I got the types of the call back handlers wrong and the C++ compiler is rightly very upset. I have fixed the problem and added a test to the demo software. This works well under Windows with Visual C++ 6.0. I have seen this compile clean under G++ 2.95.2 on FreeBSD. But it does not run because of undefined symbol "cout" (which should not be used as we use std::cout everywhere). Attached are two files: Demo\example.cxx adds a test function "kw" to the Demo. Include\CXX_Extensions.h contains the fix to correctly support keyword functions. Example output: Python 1.5.2 (#0, Apr 13 1999, 10:51:12) [MSC 32 bit (Intel)] on win32 Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
import example example.kw <built-in method kw of tuple object at 8285d8> example.kw.__doc__ 'kw()' example.kw('fred',12,name='barry',size='big',test=1) Called with 2 normal arguments. and with 3 keyword arguments: size name test 0
BArry
I'm curious about the asymmetry between getattr and setattr in CXX_Extensions.h: I don't see the setattr equivalent to virtual Object getattr_methods( const char *_name ) Is this because it hasn't been implemented or because it isn't needed? I'm asking mainly to see whether I understand what's going on with CXX, rather than from any immediate need to get/set member data. Thanks, Phil
getattr_methods is a helper function. Its job is to return a function object for any of the objects C++ methods that are referenced and to deal with references to __methods__. For objects with functions you must call getattr_methods() from your getattr() after dealing with all the non-function attributes your object has. Here is an example taken from CXX\Demo\r.cxx Py::Object r::getattr( const char *name ) { if(std::string(name) == "c") return Py::Float(300.0); if(std::string(name) == "start") return Py::Int(start); return getattr_methods( name ); } setattr is not allowed to create functions or mess up __methods__ so you simply handle your non-function attributes and throw Py::NameError for all you know nothing about. BArry
Barry Scott writes:
setattr is not allowed to create functions or mess up __methods__ so you simply handle your non-function attributes and throw Py::NameError for all you know nothing about.
Thanks, that lifted the fog a little. Here's a couple of patches to r.h and r.cxx that set an attribute, for the mailing list archive and, in case you want to expand the demo to exercise this: *** r.h 2000/05/17 18:00:05 1.1 --- r.h 2000/05/17 18:20:51 *************** *** 8,13 **** --- 8,15 ---- // Making an extension object class r: public Py::PythonExtension<r> { + private: + Py::Object setme; public: long start; long stop; *************** *** 54,59 **** --- 56,62 ---- // override functions from PythonExtension virtual Py::Object repr(); virtual Py::Object getattr( const char *name ); + virtual int setattr( const char *name, const Py::Object & ); virtual int sequence_length(); virtual Py::Object sequence_item( int i ); *** r.cxx 2000/05/04 18:46:23 1.1 --- r.cxx 2000/05/17 18:36:18 *************** *** 43,51 **** --- 43,66 ---- if(std::string(name) == "start") return Py::Int(start); + if(std::string(name) == "setme") + return setme; + return getattr_methods( name ); } + int r::setattr( const char *name,const Py::Object& rhs ) + { + + if(std::string(name) == "setme"){ + setme=rhs; + return(0); + } + + throw Py::AttributeError ("setAttr failed.");; + } + + // "regular" methods... Py::Object r::amethod( const Py::Tuple &t ) { *************** *** 81,86 **** --- 96,102 ---- behaviors().doc("r objects: start, stop, step"); behaviors().supportRepr(); behaviors().supportGetattr(); + behaviors().supportSetattr(); behaviors().supportSequenceType(); add_varargs_method("amethod", &r::amethod, Python 1.5.2 (#2, Aug 26 1999, 22:59:52) [C] on sunos5 Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
import example my_r=example.r(1,12,4) my_r.setme my_r.setme=[1,2,3] my_r.setme [1, 2, 3]
The example that I just circulated to demonstrate setattr threw an exception if the attribute wasn't found. But the exception is silently cleared in PythonType::setattr_handler: *** cxx_extensions.cxx 2000/05/08 23:35:08 1.1 --- cxx_extensions.cxx 2000/05/17 20:38:29 *************** *** 353,359 **** } catch( Py::Exception & ) { ! return 0; } } --- 353,360 ---- } catch( Py::Exception & ) { ! //return 0; ignore all exceptions?? ! return Py::Null(); } }
Phil Austin writes:
} catch( Py::Exception & ) { ! //return 0; ignore all exceptions?? ! return Py::Null(); } }
Obviously -- this doesn't compile, given the signature for setattr_handler. Since I don't understand why these handlers catch the exceptions in the first place (instead of letting them propagate), I'll let somebody else propose the correct fix. Regards, Phil
If we do not catch the exception Python will abort - remember that Python is C code not C++ and cannot deal with exceptions. The C++ exception will be converted into a Python exception. If you test your setatr version of the example you should see the exception in Python. BArry
-----Original Message----- From: c++-sig-admin@python.org [mailto:c++-sig-admin@python.org]On Behalf Of Phil Austin Sent: 17 May 2000 22:27 To: Barry Scott; c++-sig@python.org Subject: [C++-SIG] Re: bug in setattr_handler?
Phil Austin writes:
} catch( Py::Exception & ) { ! //return 0; ignore all exceptions?? ! return Py::Null(); } }
Obviously -- this doesn't compile, given the signature for setattr_handler. Since I don't understand why these handlers catch the exceptions in the first place (instead of letting them propagate), I'll let somebody else propose the correct fix.
Regards, Phil
_______________________________________________ C++-SIG maillist - C++-SIG@python.org http://www.python.org/mailman/listinfo/c++-sig
Barry Scott writes:
If you test your setatr version of the example you should see the exception in Python.
Right, returning -1 from setattr_handler did the trick. I guess this need to be changed on all the handlers that return int or long? Regards Phil.
I have commited to SOurceForge the fixes to return values from the handler functions. Exceptions show up straight away how. BArry
-----Original Message----- From: c++-sig-admin@python.org [mailto:c++-sig-admin@python.org]On Behalf Of Phil Austin Sent: 18 May 2000 19:20 To: Barry Scott Cc: Python C++-Sig Subject: RE: [C++-SIG] Re: bug in setattr_handler?
Barry Scott writes:
If you test your setatr version of the example you should see the exception in Python.
Right, returning -1 from setattr_handler did the trick. I guess this need to be changed on all the handlers that return int or long?
Regards Phil.
_______________________________________________ C++-SIG maillist - C++-SIG@python.org http://www.python.org/mailman/listinfo/c++-sig
In the version of CXX I have (dated 2000-4-30), calling Callable.apply() with no arguments evokes ! Object apply(PyObject* pargs = 0) const { ! return apply (Tuple(pargs)); which produces an exceptions.TypeError on my machine (solaris with KCC). My quick fix was to remove the default argment and add another override: *** CXX_Objects.h 2000/05/09 23:33:15 1.4 --- CXX_Objects.h 2000/05/09 23:36:23 *************** *** 1773,1786 **** return pyob && PyCallable_Check (pyob); } // Call Object apply(const Tuple& args) const { return asObject(PyObject_CallObject(ptr(), args.ptr())); } ! Object apply(PyObject* pargs = 0) const { ! return apply (Tuple(pargs)); ! } }; class Module: public Object { --- 1773,1792 ---- return pyob && PyCallable_Check (pyob); } + // Call Object apply(const Tuple& args) const { return asObject(PyObject_CallObject(ptr(), args.ptr())); } ! Object apply(PyObject* pargs) const { ! return apply (Tuple(pargs)); ! } ! ! Object apply(void) const { ! return asObject(PyObject_CallObject(ptr(), (PyObject*) NULL)); ! } ! }; class Module: public Object { Regards, Phil
This is clearly an error, a rather famous one at that (it is in Meyer's book). I will fix it as my penance. Blushingly-yours-in-Python, P.
-----Original Message----- From: c++-sig-admin@python.org [mailto:c++-sig-admin@python.org]On Behalf Of Phil Austin Sent: Tuesday, May 09, 2000 4:40 PM To: Barry Scott Cc: c++-sig@python.org Subject: [C++-SIG] Callable.apply() throws exceptions.TypeError
In the version of CXX I have (dated 2000-4-30), calling Callable.apply() with no arguments evokes
! Object apply(PyObject* pargs = 0) const { ! return apply (Tuple(pargs));
which produces an exceptions.TypeError on my machine (solaris with KCC). My quick fix was to remove the default argment and add another override:
*** CXX_Objects.h 2000/05/09 23:33:15 1.4 --- CXX_Objects.h 2000/05/09 23:36:23 *************** *** 1773,1786 **** return pyob && PyCallable_Check (pyob); }
// Call Object apply(const Tuple& args) const { return asObject(PyObject_CallObject(ptr(), args.ptr())); }
! Object apply(PyObject* pargs = 0) const { ! return apply (Tuple(pargs)); ! } };
class Module: public Object { --- 1773,1792 ---- return pyob && PyCallable_Check (pyob); }
+ // Call Object apply(const Tuple& args) const { return asObject(PyObject_CallObject(ptr(), args.ptr())); }
! Object apply(PyObject* pargs) const { ! return apply (Tuple(pargs)); ! } ! ! Object apply(void) const { ! return asObject(PyObject_CallObject(ptr(), (PyObject*) NULL)); ! } ! };
class Module: public Object {
Regards, Phil
_______________________________________________ C++-SIG maillist - C++-SIG@python.org http://www.python.org/mailman/listinfo/c++-sig
participants (3)
-
Barry Scott -
Paul F. Dubois -
Phil Austin