/* ======= otr.i ======= */ %module otr // [ some includes ] %{ void check_and_abort(const char * f, int l) { if (PyErr_Occurred() != NULL) { PyObject *type, *value, *traceback; PyErr_Fetch(&type, &value, &traceback); fprintf(stderr, "%s:%d FATAL: Exception in callback: %s\n", f, l, PyString_AsString(value)); abort(); } } void prepare_python_callback(void *opdata, const char * name, PyObject **cb_func, PyObject **kwargs) { Py_ssize_t len = PySequence_Size(opdata); check_and_abort(__FILE__,__LINE__); PyObject *cb_obj = PySequence_GetItem(opdata, 0); check_and_abort(__FILE__,__LINE__); *cb_func = PyObject_GetAttrString(cb_obj, name); check_and_abort(__FILE__,__LINE__); PyObject *args_opdata = NULL; if (len >= 2) args_opdata = PySequence_GetItem(opdata, 1); check_and_abort(__FILE__,__LINE__); *kwargs = PyDict_New(); PyDict_SetItemString(*kwargs, "opdata", args_opdata); check_and_abort(__FILE__,__LINE__); Py_XDECREF(args_opdata); Py_DECREF(cb_obj); } OtrlPolicy wrap_ops_policy(void *opdata, ConnContext *context) { const char * name = "policy"; PyObject *cb, *kwargs; prepare_python_callback(opdata, name, &cb, &kwargs); PyDict_SetItemString(kwargs, "context", SWIG_NewPointerObj(SWIG_as_voidptr(context), SWIGTYPE_p_p_context, 0 | 0 )); PyObject *result = PyObject_Call(cb, PyTuple_New(0), kwargs); check_and_abort(__FILE__,__LINE__); Py_DECREF(cb); // would crashes with Py_CLEAR here Py_DECREF(kwargs); unsigned int retval = (int) PyInt_AsUnsignedLongMask(result); check_and_abort(__FILE__,__LINE__); Py_DECREF(result); return retval; } void wrap_ops_update_context_list(void *opdata) { const char * name = "update_context_list"; PyObject *cb, *kwargs; prepare_python_callback(opdata, name, &cb, &kwargs); PyObject_Call(cb, PyTuple_New(0), kwargs); check_and_abort(__FILE__,__LINE__); Py_DECREF(cb); // crashes, but doesn't crash with Py_CLEAR here Py_DECREF(kwargs); } void ops_new(OtrlMessageAppOps *ops) { ops->policy = wrap_ops_policy; ops->update_context_list = wrap_ops_update_context_list; } %} %rename(otrl_message_sending) wrap_otrl_message_sending; %inline %{ PyObject* wrap_otrl_message_sending(OtrlUserState us, PyObject *ops, PyObject *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message, OtrlTLV *tlvs, void (*add_appdata)(void *data, ConnContext *context), void *data) { OtrlMessageAppOps *c_ops = (OtrlMessageAppOps *) malloc(sizeof(OtrlMessageAppOps)); ops_new(c_ops); PyObject * ops_t = PyTuple_New(2); PyTuple_SetItem(ops_t, 0, ops); PyTuple_SetItem(ops_t, 1, opdata); char * encMsg = NULL; gcry_error_t e = otrl_message_sending(us, c_ops, ops_t, accountname, protocol, recipient, message, tlvs, &encMsg, add_appdata, data); free(c_ops); Py_DECREF(ops_t); printf("otrl_message_sending finished: %d\n", e); if (e != 0) PyErr_SetObject(PyExc_RuntimeError, PyInt_FromLong(e)); else if (encMsg == NULL) { return Py_True; } else { return Py_False; } } %} /* ======= test.py ======= */ import otr; otr.otrl_init(3,1,0); us = otr.otrl_userstate_create(); class xyz: def update_context_list(self,**kwargs): print "update_context_list", kwargs def policy(self,**kwargs): print "policy", kwargs return otr.OTRL_POLICY_NEVER x = xyz() m = otr.otrl_message_sending(us, x, ("some", "thing", 0, 3, 1/3., __builtins__), "from", "proto", "to", "message", None, None, None) print m