Mercurial > pub > dyncall > bindings
diff python/pydc/pydcext.c @ 0:0cfcc391201f
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:26:28 +0100 |
parents | |
children | bf5625bb6f05 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/python/pydc/pydcext.c Thu Mar 19 22:26:28 2015 +0100 @@ -0,0 +1,278 @@ +/****************************************************************************** + ** + ** pydc - python dyncall package + ** + ** python extension package in C + ** Copyright 2007 Daniel Adler. + ** + ** December 04, 2007 + ** + *****************************************************************************/ + +#include <Python.h> +#include "dynload.h" +#include <limits.h> + +/* PyCObject destructor callback for libhandle */ + +void free_library(void* libhandle) +{ + if (libhandle != 0) + dlFreeLibrary(libhandle); +} + +/* load function */ + +static PyObject* +pydc_load(PyObject* self, PyObject* args) +{ + const char* libpath; + void* libhandle; + + if ( !PyArg_ParseTuple(args,"s", &libpath) ) return PyErr_Format(PyExc_RuntimeError, "libpath argument (string) missing"); + + libhandle = dlLoadLibrary(libpath); + + if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "dlLoadLibrary('%s') failed", libpath); + + return PyCObject_FromVoidPtr(libhandle, &free_library); +} + +/* find function */ + +static PyObject* +pydc_find(PyObject* self, PyObject* args) +{ + PyObject* pcobj; + const char* symbol; + void* libhandle; + void* funcptr; + + if ( !PyArg_ParseTuple(args,"Os", &pcobj, &symbol) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); + + libhandle = PyCObject_AsVoidPtr(pcobj); + + if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "libhandle is null"); + + funcptr = dlFindSymbol(libhandle, symbol); + if (!funcptr) + return PyErr_Format(PyExc_RuntimeError, "symbol '%s' not found", symbol); + + return PyCObject_FromVoidPtr(funcptr, NULL); +} + +/* free function */ + +static PyObject* +pydc_free(PyObject* self, PyObject* args) +{ + PyObject* pcobj; + void* libhandle; + + if ( !PyArg_ParseTuple(args,"o", &pcobj) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); + + libhandle = PyCObject_AsVoidPtr(pcobj); + + if (!libhandle) return PyErr_Format(PyExc_RuntimeError, "libhandle is NULL"); + + dlFreeLibrary(libhandle); + PyCObject_SetVoidPtr(pcobj,0); + Py_RETURN_NONE; +} + +#include "dyncall.h" +#include "dyncall_signature.h" + +DCCallVM* gpCall; + +/* call function */ + +static PyObject* +pydc_call(PyObject* self, PyObject* in_args) +{ + PyObject* pcobj_funcptr; + const char* signature; + PyObject* args; + int l; + const char* ptr; + char ch; + int pos; + void* pfunc; + + if ( !PyArg_ParseTuple(in_args,"OsO", &pcobj_funcptr, &signature, &args) ) return PyErr_Format(PyExc_RuntimeError, "argument mismatch"); + pfunc = PyCObject_AsVoidPtr(pcobj_funcptr); + if ( !pfunc ) return PyErr_Format( PyExc_RuntimeError, "function pointer is NULL" ); + l = PyTuple_Size(args); + + ptr = signature; + pos = 0; + + dcReset(gpCall); + + while ( (ch = *ptr) != '\0' && ch != ')' ) + { + PyObject* po; + + int index = pos+1; + + if (pos > l) return PyErr_Format( PyExc_RuntimeError, "expecting more arguments" ); + + po = PyTuple_GetItem(args,pos); + + switch(ch) + { + case DC_SIGCHAR_BOOL: + { + DCbool b; + if ( !PyBool_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a bool", index ); + b = (Py_True == po) ? DC_TRUE : DC_FALSE; + dcArgBool(gpCall, b); + } + break; + case DC_SIGCHAR_CHAR: + { + DCchar c; + if ( PyString_Check(po) ) + { + // Py_ssize_t l; + size_t l; + char* s; + l = PyString_GET_SIZE(po); + if (l != 1) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string with length of 1 (a char string)", index ); + s = PyString_AsString(po); + c = (DCchar) s[0]; + } + else if ( PyInt_Check(po) ) + { + long l; + l = PyInt_AsLong(po); + if ( (l > CHAR_MAX) || (l < CHAR_MIN)) return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a char code", index ); + c = (DCchar) l; + } + else return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a char", index ); + dcArgChar(gpCall, c); + } + break; + case DC_SIGCHAR_SHORT: + { + DCshort s; + long v; + if ( !PyInt_Check(po) ) + return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a short int", index ); + v = PyInt_AS_LONG(po); + if ( (v < SHRT_MIN) || (v > SHRT_MAX) ) + return PyErr_Format( PyExc_RuntimeError, "value out of range at argument %d - expecting a short value", index ); + s = (DCshort) v; + dcArgShort(gpCall, s); + } + break; + case DC_SIGCHAR_INT: + { + long v; + if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); + v = PyInt_AS_LONG(po); + dcArgInt(gpCall, (DCint) v ); + } + break; + case DC_SIGCHAR_LONG: + { + long v; + if ( !PyInt_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting an int", index ); + v = PyInt_AsLong(po); + + } + break; + case DC_SIGCHAR_LONGLONG: + { + PY_LONG_LONG pl; + DClonglong dl; + if ( !PyLong_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a long long", index ); + pl = PyLong_AsLongLong(po); + dl = (DClonglong) pl; + dcArgLongLong(gpCall, dl ); + } + break; + case DC_SIGCHAR_FLOAT: + { + DCfloat f; + if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index ); + f = (float) PyFloat_AsDouble(po); + dcArgFloat(gpCall, f); + } + break; + case DC_SIGCHAR_DOUBLE: + { + double d; + if (!PyFloat_Check(po)) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expeecting a float", index ); + d = PyFloat_AsDouble(po); + dcArgDouble(gpCall, d); + } + break; + case DC_SIGCHAR_POINTER: + { + DCpointer ptr; + if ( PyString_Check(po) ) { + ptr = (DCpointer) PyString_AsString(po); + } else if ( PyLong_Check(po) ) { + ptr = (DCpointer) ( (DCint) PyLong_AsLongLong(po) ); + } else { + return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a promoting pointer-type (int,string)", index ); + } + dcArgPointer(gpCall, ptr ); + } + break; + case 'S': + { + char* p; + if (!PyString_Check(po) ) return PyErr_Format( PyExc_RuntimeError, "argument mismatch at pos %d - expecting a string", index ); + p = PyString_AsString(po); + dcArgPointer(gpCall, (DCpointer) p ); + } + break; + default: return PyErr_Format( PyExc_RuntimeError, "unknown signature character '%c'", ch); + } + + ++pos; ++ptr; + + } + + if (pos != l) return PyErr_Format( PyExc_RuntimeError, "too many arguments"); + + if (ch == '\0') return PyErr_Format( PyExc_RuntimeError, "return value missing in signature"); + + ch = *++ptr; + + switch(ch) + { + case DC_SIGCHAR_VOID: dcCallVoid(gpCall, pfunc); Py_RETURN_NONE; + case DC_SIGCHAR_BOOL: return Py_BuildValue("i", dcCallBool(gpCall, pfunc) ); + case DC_SIGCHAR_INT: return Py_BuildValue("i", dcCallInt(gpCall, pfunc) ); + case DC_SIGCHAR_LONGLONG: return Py_BuildValue("L", (unsigned long long) dcCallLongLong(gpCall, pfunc) ); + case DC_SIGCHAR_FLOAT: return Py_BuildValue("f", dcCallFloat(gpCall, pfunc) ); + case DC_SIGCHAR_DOUBLE: return Py_BuildValue("d", dcCallDouble(gpCall, pfunc) ); + case 's': return Py_BuildValue("s", dcCallPointer(gpCall, pfunc) ); + case DC_SIGCHAR_POINTER: return Py_BuildValue("p", dcCallPointer(gpCall, pfunc) ); + default: return PyErr_Format( PyExc_RuntimeError, "invalid return type signature" ); + } +} + + +static PyMethodDef pydcMethods[] = { + {"load", pydc_load, METH_VARARGS, "load library"}, + {"find", pydc_find, METH_VARARGS, "find symbols"}, + {"free", pydc_free, METH_VARARGS, "free library"}, + {"call", pydc_call, METH_VARARGS, "call function"}, + {NULL,NULL,0,NULL} +}; + +PyMODINIT_FUNC +initpydcext(void) +{ + PyObject* m; + m = Py_InitModule("pydcext", pydcMethods); + if (m == NULL) + return; + gpCall = dcNewCallVM(4096); +} + +