summaryrefslogtreecommitdiffstats
path: root/dcoppython/shell/pcop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dcoppython/shell/pcop.cpp')
-rw-r--r--dcoppython/shell/pcop.cpp770
1 files changed, 770 insertions, 0 deletions
diff --git a/dcoppython/shell/pcop.cpp b/dcoppython/shell/pcop.cpp
new file mode 100644
index 00000000..d7c4adc6
--- /dev/null
+++ b/dcoppython/shell/pcop.cpp
@@ -0,0 +1,770 @@
+/***************************************************************************
+ * Copyright (C) 2003 by Julian Rockey (linux@jrockey.com) *
+ * Original code by Torben Weis *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+
+
+#include "pcop.h"
+
+#include <kdebug.h>
+
+#include <qapplication.h>
+#include <qcstring.h>
+#include <qdatastream.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstring.h>
+
+#include <dcopclient.h>
+
+#include <assert.h>
+
+#include "marshaller.h"
+#include "importedmodules.h"
+
+namespace PythonDCOP {
+
+ PCOPObject::PCOPObject(PyObject *py_obj) :
+ DCOPObject(), m_py_obj(py_obj)
+ {
+ m_methods.setAutoDelete(true);
+ }
+
+ PCOPObject::PCOPObject(PyObject *py_obj, const char *objid) :
+ DCOPObject(QCString(objid)), m_py_obj(py_obj)
+ {
+ m_methods.setAutoDelete(true);
+ }
+
+ PCOPObject::~PCOPObject()
+ {
+ }
+
+ bool PCOPObject::process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+ {
+ bool result = py_process(fun,data,replyType,replyData);
+ if (PyErr_Occurred()) {
+ kdDebug(70001) << "Error! About to print..." << endl;
+ PyErr_Print();
+ kdDebug(70001) << "About to clear..." << endl;
+ PyErr_Clear();
+ kdDebug(70001) << "Error handled." << endl;
+ }
+ return result;
+ }
+
+ bool PCOPObject::py_process(const QCString &fun, const QByteArray &data,
+ QCString& replyType, QByteArray &replyData)
+ {
+
+ kdDebug(70001) << "PCOPObject::process - fun=" << fun << " replyType=" << replyType << endl;
+
+ PCOPMethod *meth = matchMethod(fun);
+ if (!meth) {
+ kdDebug(70001) << "Could not match method name" << endl;
+ }
+
+ if (meth) {
+
+ kdDebug(70001) << "m_py_obj=" << m_py_obj << " meth->name=" << meth->name() << " meth->name.data=" << meth->name().data() << endl;
+ if (meth->name().isNull()) { kdDebug(70001) << "meth name is null" << endl; return false; }
+// if (!PyObject_HasAttrString(m_py_obj, meth->name().data())) {
+// kdDebug(70001) << "Method registered, but no python method found" << endl;
+// return false;
+// }
+
+ QDataStream str_arg(data, IO_ReadOnly);
+ PyObject *args = PyTuple_New( meth->paramCount() );
+ for(int c=0;c<meth->paramCount();c++) {
+ kdDebug(70001) << "Demarshalling type: " << meth->param(c)->signature() << endl;
+ PyObject *arg = meth->param(c)->demarshal(str_arg);
+ if (!arg) {
+ kdDebug(70001) << "Failed to demarshall an argument" << endl;
+ return false;
+ }
+ PyTuple_SetItem(args, c, arg );
+ }
+
+ kdDebug(70001) << "args is " << PyTuple_Size(args) << " long" << endl;
+
+// PyObject *method = PyObject_GetAttrString(m_py_obj, meth->name().data() );
+ PyObject *method = meth->pythonMethod();
+ if (!PyCallable_Check(method)) {
+ kdDebug(70001) << "Expected a callable object, but didn't get one!" << endl;
+ return false;
+ }
+
+// PyObject *function = PyMethod_Function(method);
+// PyObject *self = PyMethod_Self(method);
+// Py_INCREF(self);
+// PyTuple_SetItem(args, 0, self );
+// PyObject *result = PyObject_CallObject(function, args);
+
+// Py_DECREF(method);
+ if (PyMethod_Self(method)==NULL)
+ kdDebug(70001) << "Warning: self is null!" << endl;
+
+ kdDebug(70001) << "About to call object.." << endl;
+ PyObject *result = PyObject_CallObject(method, args);
+ kdDebug(70001) << "Finished calling object." << endl;
+
+ if (result) {
+ replyType = meth->type()->signature();
+ PCOPType repl(replyType);
+ if (repl.isMarshallable(result)) {
+ QDataStream str_repl(replyData, IO_WriteOnly);
+ repl.marshal(result,str_repl);
+ Py_DECREF(result);
+ return true;
+ } else {
+ Py_DECREF(result);
+ kdDebug(70001) << "Result of python method was not marshallable into " << replyType << endl;
+ return false;
+ }
+ }
+ else {
+ kdDebug(70001) << "null result from python method call" << endl;
+ return false;
+ }
+
+ }
+
+ return DCOPObject::process(fun,data,replyType,replyData);
+
+ }
+
+ bool PCOPObject::setMethodList(QAsciiDict<PyObject> meth_list) {
+ bool ok = true;
+
+ for(QAsciiDictIterator<PyObject> it(meth_list);
+ it.current(); ++it) {
+
+ PCOPMethod *meth = NULL;
+ if (ok) {
+ meth = new PCOPMethod(QCString(it.currentKey()));
+
+ if (!meth || !meth->setPythonMethod(it.current())) {
+ if (meth) delete meth;
+ meth=NULL;
+ m_methods.clear();
+ ok=false;
+ }
+
+ }
+
+// Py_DECREF(it.current());
+ if (meth) m_methods.insert(meth->signature(),meth);
+ }
+
+ return ok;
+ }
+
+ QCStringList PCOPObject::functions() {
+ QCStringList funcs = DCOPObject::functions();
+ for(QAsciiDictIterator<PCOPMethod> it(m_methods);
+ it.current(); ++it) {
+ PCOPMethod *meth = it.current();
+ QCString func = meth->type()->signature();
+ func += ' ';
+ func += meth->signature();
+ funcs << func;
+ }
+ return funcs;
+ }
+
+ /**
+ * For testing
+ */
+ PyObject *PCOPObject::methodList() {
+ PyObject *result = PyList_New(m_methods.count());
+ int c=0;
+ for(QAsciiDictIterator<PCOPMethod> it(m_methods);
+ it.current(); ++it, ++c) {
+ PyObject *tuple = PyTuple_New(2);
+ PyList_SetItem(result, c, tuple);
+ PyTuple_SetItem(tuple, 0, PyString_FromString(it.currentKey() ) );
+ PyTuple_SetItem(tuple, 1, it.current()->pythonMethod() );
+ }
+ return result;
+ }
+
+ PCOPMethod *PCOPObject::matchMethod(const QCString &fun) {
+ return m_methods.find(fun);
+ }
+
+
+ PCOPType::PCOPType( const QCString& type )
+ {
+ m_leftType = NULL;
+ m_rightType = NULL;
+
+ int pos = type.find( '<' );
+ if ( pos == -1 )
+ {
+ m_type = type;
+ return;
+ }
+
+ int pos2 = type.findRev( '>' );
+ if ( pos2 == -1 )
+ return;
+
+ m_type = type.left( pos );
+
+ // There may be no more than 2 types in the bracket
+ int komma = type.find( ',', pos + 1 );
+ if ( komma == -1 )
+ {
+ m_leftType = new PCOPType( type.mid( pos + 1, pos2 - pos - 1 ) );
+ }
+ else
+ {
+ m_leftType = new PCOPType( type.mid( pos + 1, komma - pos - 1 ) );
+ m_rightType = new PCOPType( type.mid( komma + 1, pos2 - komma - 1 ) );
+ }
+ }
+
+ PCOPType::~PCOPType()
+ {
+ if (m_leftType) delete m_leftType;
+ if (m_rightType) delete m_rightType;
+ }
+
+ QCString PCOPType::signature() const
+ {
+ QCString str = m_type;
+ if ( m_leftType )
+ {
+ str += "<";
+ str += m_leftType->signature();
+
+ if ( m_rightType )
+ {
+ str += ",";
+ str += m_rightType->signature();
+ }
+
+ str += ">";
+ }
+
+ return str;
+ }
+
+ bool PCOPType::marshal( PyObject* obj, QDataStream& str ) const
+ {
+ return Marshaller::instance()->marshal(*this, obj, str);
+ }
+
+ bool PCOPType::isMarshallable( PyObject *obj ) const
+ {
+ return Marshaller::instance()->canMarshal(*this, obj);
+ }
+
+ PyObject* PCOPType::demarshal( QDataStream& str ) const
+ {
+ return Marshaller::instance()->demarshal(*this, str);
+ }
+
+ PCOPMethod::PCOPMethod( const QCString& signature ) :
+ m_py_method(NULL)
+ {
+
+ m_type = 0;
+ m_params.setAutoDelete( TRUE );
+
+ // Find the space that separates the type from the name
+ int k = signature.find( ' ' );
+ if ( k == -1 )
+ return;
+
+ // Create the return type from the string
+ m_type = new PCOPType( signature.left( k ) );
+
+ // Find the brackets
+ int i = signature.find( '(' );
+ if ( i == -1 )
+ return;
+ int j = signature.find( ')' );
+ if ( j == -1 )
+ return;
+
+ // Extract the name
+ m_name = signature.mid( k + 1, i - k - 1 );
+
+ // Strip the parameters
+ QCString p = signature.mid( i + 1, j - i - 1 ).stripWhiteSpace();
+
+ if ( !p.isEmpty() ) {
+ // Make the algorithm terminate
+ p += ",";
+
+ // Iterate over the parameters
+ int level = 0;
+ int start = 0;
+ int len = p.length();
+ for( int i = 0; i < len; ++i )
+ {
+ // Found a comma? Then we reached the end of a parameter
+ if ( p[i] == ',' && level == 0 )
+ {
+ // Find the space that separates name from type.
+ int space = p.find( ' ', start );
+
+ if ( space == -1 || space > i ) // unnamed parameter
+ space = i;
+
+ PCOPType* type = new PCOPType( p.mid( start, space - start ) );
+ m_params.append( type );
+
+ // Start of the next parameter
+ start = i + 1;
+ }
+ else if ( p[i] == '<' )
+ ++level;
+ else if ( p[i] == '>' )
+ --level;
+ }
+ }
+
+ m_signature = m_name;
+ m_signature += "(";
+
+ QListIterator<PCOPType> it( m_params );
+ for( ; it.current(); ++it )
+ {
+ if ( !it.atFirst() )
+ m_signature += ',';
+ m_signature += it.current()->signature();
+ }
+
+ m_signature += ")";
+
+ }
+
+ PCOPMethod::~PCOPMethod()
+ {
+ delete m_type;
+ if (m_py_method) {
+ Py_DECREF(m_py_method);
+ }
+ }
+
+ bool PCOPMethod::setPythonMethod(PyObject *method) {
+ if (method && PyMethod_Check(method)) {
+
+ if (m_py_method) {
+ Py_DECREF(m_py_method);
+ }
+
+ m_py_method = method;
+ Py_INCREF(m_py_method);
+
+ return true;
+ }
+ return false;
+ }
+
+ int PCOPMethod::paramCount() const
+ {
+ return m_params.count();
+ }
+
+ PCOPType* PCOPMethod::param( int i )
+ {
+ return m_params.at( i );
+ }
+
+ const PCOPType* PCOPMethod::param( int i ) const
+ {
+ return ((PCOPMethod*)this)->m_params.at( i );
+ }
+
+ PCOPClass::PCOPClass( const QCStringList& methods )
+ {
+ m_methods.setAutoDelete( true );
+
+ QCStringList::ConstIterator it = methods.begin();
+ for( ; it != methods.end(); ++it )
+ {
+ PCOPMethod* m = new PCOPMethod( *it );
+ m_methods.insert( m->m_name, m );
+ }
+ }
+
+ PCOPClass::~PCOPClass()
+ {
+ }
+
+ const PCOPMethod* PCOPClass::method( const QCString &name, PyObject *argTuple )
+ {
+ if ( !argTuple )
+ return m_methods[ name ];
+
+ QAsciiDictIterator<PCOPMethod> it( m_methods );
+ for (; it.current(); ++it )
+ if ( it.currentKey() == name &&
+ it.current()->paramCount() == PyTuple_Size( argTuple ) )
+ {
+ // ok, name and argument count match, now check if the python
+ // can be marshalled to the qt/dcop type
+
+ PCOPMethod *m = it.current();
+
+ bool fullMatch = true;
+
+ for ( int i = 0; i < m->paramCount(); ++i )
+ if ( !m->param( i )->isMarshallable( PyTuple_GetItem( argTuple, i ) ) )
+ {
+ fullMatch = false;
+ break;
+ }
+
+ if ( fullMatch )
+ return m;
+ }
+
+ return 0;
+ }
+
+
+ // Client
+
+ Client::Client() : m_dcop(NULL), m_qapp(NULL)
+ {
+ ImportedModules::setInstance( new ImportedModules );
+ int argc = 0;
+ char **argv = NULL;
+ m_qapp = new QApplication(argc,argv,false);
+ }
+
+ Client::~Client()
+ {
+// if (m_qapp) delete m_qapp;
+ if (m_dcop) delete m_dcop;
+ }
+
+ void Client::processEvents() {
+ if (m_qapp) {
+// kdDebug(70001) << "Processing events..." << endl;
+ m_qapp->processEvents();
+ }
+ }
+
+ DCOPClient *Client::dcop() {
+ if ( !m_dcop ) {
+ m_dcop = new DCOPClient;
+ if ( !m_dcop->attach() )
+ kdWarning(70001) << "Could not attach to DCOP server";
+ }
+ return m_dcop;
+ }
+
+ Client *Client::instance() { return s_instance; }
+ Client *Client::s_instance = new Client;
+
+
+////////////////////////////////////////////////
+//
+// Methods accessed by python
+//
+////////////////////////////////////////////////
+
+ PyObject* dcop_call( PyObject* /*self*/, PyObject* args )
+ {
+ char *arg1;
+ char *arg2;
+ char *arg3;
+ PyObject* tuple;
+
+ if ( !PyArg_ParseTuple( args, (char*)"sssO", &arg1, &arg2, &arg3, &tuple ) )
+ return NULL;
+
+ if ( !PyTuple_Check( tuple ) )
+ return NULL;
+
+ QByteArray replyData;
+ QCString replyType;
+ QByteArray data;
+ QDataStream params( data, IO_WriteOnly );
+
+ QCString appname( arg1 );
+ QCString objname( arg2 );
+ QCString funcname( arg3 );
+
+ //
+ // Remove escape characters
+ //
+ if ( objname[0] == '_' )
+ objname = objname.mid( 1 );
+ if ( funcname[0] == '_' )
+ funcname = funcname.mid( 1 );
+
+ DCOPClient* dcop = Client::instance()->dcop();
+
+ //
+ // Determine which functions are available.
+ //
+ bool ok = false;
+ QCStringList funcs = dcop->remoteFunctions( appname, objname, &ok );
+ if ( !ok )
+ {
+ PyErr_SetString( PyExc_RuntimeError, "Object is not accessible." );
+ return NULL;
+ }
+
+ // for ( QCStringList::Iterator it = funcs.begin(); it != funcs.end(); ++it ) {
+ // qDebug( "%s", (*it).data() );
+ // }
+
+ //
+ // Create a parse tree and search for the method
+ //
+ // ### Check wether that is sane
+ PCOPClass c( funcs );
+
+ // qDebug("Parsing done.");
+
+ // Does the requested method exist ?
+ const PCOPMethod* m = c.method( funcname, tuple );
+ if ( !m )
+ {
+ PyErr_SetString( PyExc_RuntimeError, "DCOP: Unknown method." );
+ return NULL;
+ }
+
+ QCString signature = m->signature();
+ kdDebug(70001) << "The signature is " << signature.data() << endl;
+
+ kdDebug(70001) << "The method takes " << m->paramCount() << " parameters" << endl;
+
+ //
+ // Marshal the parameters.
+ //
+
+ int param_count = m->paramCount();
+ for( int p = 0; p < param_count; ++p )
+ {
+ PyObject* o = PyTuple_GetItem( tuple, p );
+ // #### Check for errors
+ if ( !m->param( p )->marshal( o, params ) )
+ {
+ kdDebug(70001) << "QD: Could not marshal paramater %i" << p << endl;
+ PyErr_SetString( PyExc_RuntimeError, "DCOP: marshaling failed" );
+ return NULL;
+ }
+ }
+
+ kdDebug(70001) << "Calling " << appname.data() << " " << objname.data() << " " << signature.data() << endl;
+
+// ASSERT( Client::instance()->dcop() != 0 );
+ ASSERT(dcop);
+
+ if ( !dcop->call( appname, objname, signature, data, replyType, replyData ) )
+ {
+ PyErr_SetString( PyExc_RuntimeError, "DCOP: call failed" );
+ return NULL;
+ }
+
+ kdDebug(70001) << "The return type is " << replyType.data() << endl;
+
+ //
+ // Now decode the return type.
+ //
+ // ### Check wether that was sane
+ PCOPType type( replyType );
+ QDataStream reply(replyData, IO_ReadOnly);
+ return type.demarshal( reply );
+
+ }
+
+ PyObject* application_list( PyObject */*self*/, PyObject */*args*/ )
+ {
+ QCStringList apps = Client::instance()->dcop()->registeredApplications();
+
+ PyObject *l = PyList_New( apps.count() );
+
+ QCStringList::ConstIterator it = apps.begin();
+ QCStringList::ConstIterator end = apps.end();
+ unsigned int i = 0;
+ for (; it != end; ++it, i++ )
+ PyList_SetItem( l, i, PyString_FromString( (*it).data() ) );
+
+ return l;
+ }
+
+ PyObject *object_list( PyObject */*self*/, PyObject *args) {
+ const char *app;
+ if (PyArg_ParseTuple(args, (char*)"s", &app)) {
+ QCStringList objects = Client::instance()->dcop()->remoteObjects(QCString(app));
+ return make_py_list(objects);
+ }
+ return NULL;
+ }
+
+ PyObject *method_list( PyObject */*self*/, PyObject *args) {
+ const char *app, *obj;
+ if (PyArg_ParseTuple(args, (char*)"ss", &app, &obj)) {
+ QCStringList methods = Client::instance()->dcop()->remoteFunctions(QCString(app), QCString(obj) );
+ return make_py_list(methods);
+ }
+ return NULL;
+ }
+
+ PyObject *register_as( PyObject */*self*/, PyObject *args) {
+ const char *appid;
+ int add_pid = 1;
+ if (PyArg_ParseTuple(args, (char*)"s|i", &appid, &add_pid)) {
+ QCString actual_appid = Client::instance()->dcop()->registerAs(QCString(appid), add_pid!=0);
+ return PyString_FromString(actual_appid.data());
+ }
+ return NULL;
+ }
+
+ PyObject *create_dcop_object( PyObject */*self*/, PyObject *args) {
+ PyObject *py_dcop_object;
+ const char *objid = NULL;
+ if (PyArg_ParseTuple(args, (char*)"O|s", &py_dcop_object, &objid)) {
+ Py_INCREF(py_dcop_object);
+ PCOPObject *obj = objid ? new PCOPObject(py_dcop_object, objid) : new PCOPObject(py_dcop_object);
+ return PyCObject_FromVoidPtr( (void*)obj, delete_dcop_object );
+ }
+ return NULL;
+ }
+
+ /**
+ * pcop.set_method_list( <dcopobject cobject>, <method list> )
+ * where <method list> is a list of tuples
+ * [ ('method signature', python method), ... ]
+ */
+ PyObject *set_method_list( PyObject */*self*/, PyObject *args) {
+ PyObject *c_obj;
+ PyObject *method_list;
+ if (PyArg_ParseTuple(args, (char*)"OO", &c_obj, &method_list) &&
+ PyCObject_Check(c_obj) &&
+ PyList_Check(method_list)) {
+
+ // extract each tuple from the list, aborting if any is invalid
+ QAsciiDict<PyObject> meth_list;
+ int size = PyList_Size(method_list);
+ for(int c=0;c<size;c++) {
+ PyObject *tuple = PyList_GetItem(method_list,c);
+ const char *method_signature = NULL;
+ PyObject *py_method = NULL;
+ if (!PyArg_ParseTuple(tuple, (char*)"sO", &method_signature, &py_method))
+ return NULL;
+ Py_INCREF(py_method);
+ meth_list.insert(method_signature, py_method);
+ }
+
+ PCOPObject *obj = (PCOPObject*)PyCObject_AsVoidPtr(c_obj);
+ if (obj) {
+ if (!obj->setMethodList(meth_list)) return NULL;
+ }
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+ return NULL;
+ }
+
+ PyObject *get_method_list(PyObject */*self*/, PyObject *args) {
+ PyObject *c_obj;
+ if (PyArg_ParseTuple(args, (char*)"O", &c_obj)) {
+ if (PyCObject_Check(c_obj)) {
+ PCOPObject *obj = (PCOPObject*)PyCObject_AsVoidPtr(c_obj);
+ return obj->methodList();
+ }
+ }
+ return NULL;
+ }
+
+ PyObject *connect_DCOP_Signal( PyObject */*self*/, PyObject *args) {
+ const char *sender;
+ const char *senderObj;
+ const char *signal;
+ const char *receiverObj;
+ const char *slot;
+
+ int volint = 0;
+ if (PyArg_ParseTuple(args, (char*)"sssss|i", &sender, &senderObj, &signal, &receiverObj, &slot, &volint)) {
+ bool success = Client::instance()->dcop()->connectDCOPSignal(QCString(sender), QCString(senderObj), QCString(signal), QCString(receiverObj), QCString(slot), (volint == 1)?true:false);
+ return Py_BuildValue("i", success?1:0);
+ }
+ return NULL;
+ }
+
+ PyObject *disconnect_DCOP_Signal( PyObject *self, PyObject *args) {
+ const char *sender;
+ const char *senderObj;
+ const char *signal;
+ const char *receiverObj;
+ const char *slot;
+
+ if (PyArg_ParseTuple(args, (char*)"sssss", &sender, &senderObj, &signal, &receiverObj, &slot)) {
+ bool success = Client::instance()->dcop()->disconnectDCOPSignal(QCString(sender), QCString(senderObj), QCString(signal), QCString(receiverObj), QCString(slot));
+ return Py_BuildValue("i", success?1:0);
+ }
+ return NULL;
+
+ }
+
+
+
+ void delete_dcop_object(void *vp) {
+ if (vp) {
+ PCOPObject *obj = (PCOPObject*)vp;
+ delete obj;
+ }
+ }
+
+ PyObject *process_events( PyObject */*self*/, PyObject */*args*/) {
+ Client::instance()->processEvents();
+ Py_INCREF(Py_None);
+ return Py_None;
+ }
+
+ // helpers
+
+ PyObject *make_py_list( const QCStringList &qt_list) {
+ PyObject *l = PyList_New(qt_list.count());
+ uint c=0;
+ for(QCStringList::ConstIterator it = qt_list.begin();
+ it!=qt_list.end();
+ ++it,c++)
+ PyList_SetItem(l, c, PyString_FromString( (*it).data() ) );
+ return l;
+ }
+
+}
+
+
+PyMethodDef PCOPMethods[] = {
+ { (char*)"dcop_call", PythonDCOP::dcop_call, METH_VARARGS, (char*)"Make a call to DCOP." },
+ { (char*)"app_list", PythonDCOP::application_list, METH_VARARGS, (char*)"Return a list of DCOP registered application." },
+ { (char*)"obj_list", PythonDCOP::object_list, METH_VARARGS, (char*)"Return a list of objects for a DCOP registered application."},
+ { (char*)"method_list", PythonDCOP::method_list, METH_VARARGS, (char*)"Return a list of methods for a DCOP object."},
+ { (char*)"register_as", PythonDCOP::register_as, METH_VARARGS, (char*)"Register the application with DCOP."},
+ { (char*)"create_dcop_object", PythonDCOP::create_dcop_object, METH_VARARGS, (char*)"Creates a DCOP Object instance."},
+ { (char*)"process_events", PythonDCOP::process_events, METH_VARARGS, (char*)"Processes QT events."},
+ { (char*)"set_method_list", PythonDCOP::set_method_list, METH_VARARGS, (char*)"Set the list of methods for a DCOP server object."},
+ { (char*)"connect_dcop_signal", PythonDCOP::connect_DCOP_Signal, METH_VARARGS, (char*)"Connect a dcop signal."},
+ { (char*)"disconnect_dcop_signal", PythonDCOP::disconnect_DCOP_Signal, METH_VARARGS, (char*)"Disconnect a dcop signal."},
+ { NULL, NULL, 0, NULL } /* Sentinel */
+};
+
+extern "C"
+{
+
+ void initpcop()
+ {
+ (void) Py_InitModule( (char*)"pcop", PCOPMethods );
+ }
+
+}
+
+