1 /********************************************************************** 2 * 3 * SWIG Foreign Function Interface (FFI) definition for the Link Grammar 4 * shared (dynamic) library. 5 * 6 ***********************************************************************/ 7 %module clinkgrammar 8 %{ 9 10 #include <link-grammar/link-includes.h> 11 12 %} 13 14 %nodefaultdtor lg_errinfo; 15 16 #define link_public_api(x) x 17 #ifndef bool /* Prevent syntax errors if no bool. */ 18 #define bool int 19 #endif /* bool */ 20 21 %newobject dictionary_get_data_dir; 22 23 /********************************************************************** 24 * 25 * Functions that create and manipulate Linkages. 26 * When a Linkage is requested, the user is given a 27 * copy of all of the necessary information, and is responsible 28 * for freeing up the storage when he/she is finished, using 29 * the routines provided below. 30 * 31 ***********************************************************************/ 32 33 /********************************************************************** 34 * 35 * These functions allocate strings to be returned, so need to be 36 * newobject'd to avoid memory leaks 37 * 38 ***********************************************************************/ 39 40 %newobject linkage_print_diagram; 41 %typemap(newfree) char * { 42 linkage_free_diagram($1); 43 } 44 %rename("%s") linkage_print_diagram; 45 46 %newobject linkage_print_postscript; 47 %typemap(newfree) char * { 48 linkage_free_postscript($1); 49 } 50 %rename("%s") linkage_print_postscript; 51 52 %newobject linkage_print_links_and_domains; 53 %typemap(newfree) char * { 54 linkage_free_links_and_domains($1); 55 } 56 %rename("%s") linkage_print_links_and_domains; 57 58 %newobject linkage_print_constituent_tree; 59 %typemap(newfree) char * { 60 linkage_free_constituent_tree_str($1); 61 } 62 %rename("%s") linkage_print_constituent_tree; 63 64 %newobject linkage_print_disjuncts; 65 %typemap(newfree) char * { 66 linkage_free_disjuncts($1); 67 } 68 %rename("%s") linkage_print_disjuncts; 69 70 %typemap(newfree) char * { 71 linkage_free_pp_msgs($1); 72 } 73 %rename("%s") linkage_print_pp_msgs; 74 75 // Reset to default. 76 %typemap(newfree) char * { 77 free($1); 78 } 79 80 /* Error-handling facility calls. */ 81 %rename(_lg_error_formatmsg) lg_error_formatmsg; 82 %newobject lg_error_formatmsg; 83 %rename(_prt_error) prt_error; 84 /* For security, the first argument should always contain a single "%s" 85 * (e.g. "%s\n"), and the second one should always be a C string. */ 86 int prt_error(const char *, const char *); 87 88 /* 89 * A wrapper to this function is complex and is not implemented here. However, 90 * such a wrapper may not be needed anyway since this function is provided 91 * mainly for the low-level implementation of the error callback, so bound 92 * languages can free the memory of the callback data. 93 */ 94 %ignore lg_error_set_handler_data; 95 96 // Set a default newfree typemap. 97 %typemap(newfree) char * { 98 free($1); 99 } 100 101 %immutable; /* Future-proof for const definitions. */ 102 %include ../link-grammar/link-includes.h 103 %mutable; 104 105 #ifdef SWIGPYTHON 106 %extend lg_errinfo 107 { 108 %pythoncode 109 %{ 110 def formatmsg(self): 111 return _lg_error_formatmsg(self) 112 __swig_destroy__ = _clinkgrammar.delete_lg_errinfo 113 __del__ = lambda self: None 114 %} 115 } 116 117 %{ 118 static lg_error_handler default_error_handler; 119 120 static lg_errinfo *dup_lg_errinfo(lg_errinfo *lge) 121 { 122 lg_errinfo *mlge = (lg_errinfo *)malloc(sizeof(lg_errinfo)); 123 mlge->severity_label = strdup(lge->severity_label); 124 mlge->text = strdup(lge->text); 125 mlge->severity = lge->severity; 126 127 return mlge; 128 } 129 130 /** 131 * This function is installed as the C error callback when an error callback 132 * is set by the Python code to a Python function (but not when set to None 133 * or to the library default error handler). 134 * When invoked by the LG library, it calls the Python function along with 135 * its data. Both appear in func_and_data, which is a Python tuple of 2 136 * elements - a function and an arbitrary data object. 137 */ 138 static void PythonCallBack(lg_errinfo *lge, void *func_and_data) 139 { 140 lg_errinfo *mlgep = dup_lg_errinfo(lge); 141 PyObject *pylge = SWIG_NewPointerObj(SWIG_as_voidptr(mlgep), 142 SWIGTYPE_p_lg_errinfo, SWIG_POINTER_OWN); 143 PyObject *func = PyTuple_GetItem((PyObject *)func_and_data, 0); 144 PyObject *data = PyTuple_GetItem((PyObject *)func_and_data, 1); 145 146 PyObject *args = Py_BuildValue("OO", pylge, data); 147 PyObject *rc = PyEval_CallObject(func, args); /* Py LG error cb. */ 148 149 Py_DECREF(pylge); 150 Py_DECREF(args); 151 if (NULL == rc) 152 PyErr_Print(); 153 Py_XDECREF(rc); 154 } 155 %} 156 157 %typemap(in) lg_errinfo *eh_lge 158 { 159 void *argp1 = 0; 160 161 if (Py_None == $input) 162 SWIG_exception_fail(SWIG_TypeError, "in method '_py_error_default_handler', argument 1 (of type lg_errinfo *) must not be None."); 163 164 int res1 = SWIG_ConvertPtr($input, &argp1, SWIGTYPE_p_lg_errinfo, 0); 165 if (!SWIG_IsOK(res1)) { 166 SWIG_exception_fail(SWIG_ArgError(res1), "in method '_py_error_default_handler', argument 1 of type 'lg_errinfo *'"); 167 } 168 arg1 = (lg_errinfo *)(argp1); 169 } 170 171 /* The second argument of the default callback can be NULL or 172 a severity_level integer. Validate that and convert it to C int. */ 173 %typemap(in) int *pedh_data (int arg) 174 { 175 bool error = false; 176 const char errmsg[] = "The default error handler data argument (arg 2) " 177 "must be an integer (0 to lg_None) or None."; 178 179 if (Py_None == $input) 180 { 181 $1 = NULL; 182 } 183 else 184 { 185 if (!PyInt_Check($input)) 186 { 187 SWIG_exception_fail(SWIG_TypeError, errmsg); 188 error = true; 189 } 190 else 191 { 192 arg = (int)PyInt_AsLong($input); 193 } 194 195 if ((arg < 0) || (arg > lg_None)) 196 { 197 SWIG_exception_fail(SWIG_ValueError, errmsg); 198 error = true; 199 } 200 201 if (error) return NULL; 202 $1 = &arg; 203 } 204 } 205 206 %inline %{ 207 void _py_error_default_handler(lg_errinfo *eh_lge, int *pedh_data) 208 { 209 default_error_handler(eh_lge, (void *)pedh_data); 210 } 211 212 /** 213 * Set a Python function/data as the LG error handler callback. 214 * Note that because the LG library cannot directly call a Python function, 215 * the actual callback function is a C proxy function PythonCallBack() and 216 * the Python function/data is set as the C callback data. 217 */ 218 PyObject *_py_error_set_handler(PyObject *func_and_data) 219 { 220 const void *old_func_and_data = lg_error_set_handler_data(NULL); 221 PyObject *func = PyTuple_GetItem((PyObject *)func_and_data, 0); 222 lg_error_handler old_handler; 223 224 if (Py_None == func) 225 { 226 old_handler = lg_error_set_handler(NULL, NULL); 227 } 228 else 229 { 230 if (!PyCallable_Check(func)) { 231 PyErr_SetString(PyExc_TypeError, "Argument 1 must be callable"); 232 return NULL; 233 } 234 old_handler = lg_error_set_handler(PythonCallBack, func_and_data); 235 Py_INCREF(func_and_data); 236 } 237 238 if (NULL == (PyObject *)old_handler) 239 Py_RETURN_NONE; 240 241 if (PythonCallBack == old_handler) 242 { 243 func = PyTuple_GetItem((PyObject *)old_func_and_data, 0); 244 Py_INCREF(func); 245 Py_XDECREF(old_func_and_data); 246 return func; 247 } 248 249 /* This must be the first call. Grab the C default error handler. */ 250 default_error_handler = old_handler; 251 252 /* Signify this is the default error handler by a string object. */ 253 return Py_BuildValue("s", ""); 254 } 255 256 PyObject *_py_error_printall(PyObject *func_and_data) 257 { 258 Py_INCREF(func_and_data); 259 int n = lg_error_printall(PythonCallBack, func_and_data); 260 Py_DECREF(func_and_data); 261 262 PyObject *py_n = PyInt_FromLong(n); 263 return py_n; 264 } 265 266 void delete_lg_errinfo(lg_errinfo *lge) { 267 if (NULL == lge) return; /* Was None - nothing to free. */ 268 free((void *)lge->severity_label); 269 free((void *)lge->text); 270 free((void *)lge); 271 } 272 273 /** 274 * incref/decref a Python object. 275 * Currently used on the Dictionary object when a Sentence object is created/deleted, 276 * because the Sentence object includes a reference to the Dictionary structure. 277 */ 278 void _py_incref(PyObject *x) 279 { 280 Py_INCREF(x); 281 } 282 283 void _py_decref(PyObject *x) 284 { 285 Py_DECREF(x); 286 } 287 %} 288 #endif /* SWIGPYTHON */ 289