diff --git a/packages/pyswip/python.c b/packages/pyswip/python.c index b81f4091b..d6d9747d7 100644 --- a/packages/pyswip/python.c +++ b/packages/pyswip/python.c @@ -1,8 +1,13 @@ #include #include +#ifdef HAVE_STAT +#undef HAVE_STAT +#endif #include #include +static atom_t ATOM_true, ATOM_false; + static foreign_t init_python(void) { @@ -18,6 +23,162 @@ end_python(void) return TRUE; } +static int +python_import(term_t mname, term_t mod) +{ + char *s; + size_t len; + PyObject *pName, *pModule; + + if ( !PL_get_nchars(mname, &len, &s, CVT_ALL|CVT_EXCEPTION) ) { + return FALSE; + } + pName = PyString_FromString(s); + if (pName == NULL) { + return FALSE; + } +PyRun_SimpleString("import sys"); +PyRun_SimpleString("sys.path.append(\"/Users/vsc/Yap/bins/osx/packages/pyswip\")"); +//PyRun_SimpleString("import multiply"); + pModule = PyImport_Import(pName); + PyErr_Print(); + Py_DECREF(pName); + if (pModule == NULL) { + return FALSE; + } + return PL_unify_pointer(mod, (void *)pModule); +} + +static foreign_t +python_f(term_t tmod, term_t fname, term_t tf) +{ + char *s; + size_t len; + PyObject *pF, *pModule; + void **mp = (void *)&pModule; + + if ( !PL_get_pointer(tmod, mp) ) { + PyObject *pName; + + if ( !PL_get_nchars(fname, &len, &s, CVT_ALL|CVT_EXCEPTION) ) { + return FALSE; + } + pName = PyString_FromString(s); + if (pName == NULL) { + return FALSE; + } + pModule = PyImport_Import(pName); + } + if ( !PL_get_nchars(fname, &len, &s, CVT_ALL|CVT_EXCEPTION) ) { + return FALSE; + } + pF = PyObject_GetAttrString(pModule, s); + if (pF == NULL || ! PyCallable_Check(pF)) { + return FALSE; + } + return PL_unify_pointer(tf, (void *)pF); +} + +static PyObject * +term_to_python(term_t t) +{ + switch (PL_term_type(t)) { + case PL_VARIABLE: + return NULL; + case PL_ATOM: + { + char *s; + + if (!PL_get_atom_chars(t, &s)) + return NULL; + return PyByteArray_FromStringAndSize(s, strlen(s) ); + } + case PL_INTEGER: + { + int64_t j; + if (!PL_get_int64_ex(t, &j)) + return NULL; + return PyInt_FromLong(j); + } + case PL_STRING: + { + char *s; + size_t len; + + if (!PL_get_string_chars(t, &s, &len)) + return NULL; + return PyByteArray_FromStringAndSize(s, len ); + } + case PL_FLOAT: + { + double fl; + if (!PL_get_float(t, &fl)) + return NULL; + return PyFloat_FromDouble( fl ); + } + case PL_TERM: + return NULL; + } + return NULL; +} + +static foreign_t +output_python_term(PyObject *pVal, term_t t) +{ + if (PyLong_Check(pVal)) { + return PL_unify_int64(t, PyLong_AsLong(pVal)); + } else if (PyInt_Check(pVal)) { + return PL_unify_int64(t, PyInt_AsLong(pVal)); + } else if (PyBool_Check(pVal)) { + if (pVal == Py_True) { + return PL_unify_atom(t, ATOM_true); + } else { + return PL_unify_atom(t, ATOM_false); + } + } else if (PyFloat_Check(pVal)) { + return PL_unify_float(t, PyFloat_AsDouble(pVal)); + } else if (PyByteArray_Check(pVal)) { + atom_t tmp_atom = PL_new_atom(PyByteArray_AsString(pVal)); + return PL_unify_atom(t, tmp_atom); + } else { + return FALSE; + } +} + +static foreign_t +python_apply(term_t tin, term_t targs, term_t tf) +{ + PyObject *pF, *pArgs, *pValue; + void **mpf = (void *)&pF; + int i, arity; + atom_t aname; + foreign_t out; + term_t targ = PL_new_term_ref(); + + if ( !PL_get_pointer(tin, mpf) ) { + return FALSE; + } + if (! PL_get_name_arity( targs, &aname, &arity) ) { + return FALSE; + } + pArgs = PyTuple_New(arity); + for (i = 0 ; i < arity; i++) { + PyObject *pArg; + if (! PL_get_arg(i+1, targs, targ) ) + return FALSE; + pArg = term_to_python(targ); + if (pArg == NULL) + return NULL; + /* pArg reference stolen here: */ + PyTuple_SetItem(pArgs, i, pArg); + } + pValue = PyObject_CallObject(pF, pArgs); + Py_DECREF(pArgs); + out = output_python_term(pValue, tf); + Py_DECREF(pValue); + return out; +} + static foreign_t python_run_command(term_t cmd) { @@ -39,10 +200,14 @@ install_python(void) { // FUNCTOR_dot2 = PL_new_functor(PL_new_atom("."), 2); // FUNCTOR_equal2 = PL_new_functor(PL_new_atom("="), 2); // FUNCTOR_boolop1 = PL_new_functor(PL_new_atom("@"), 1); - // ATOM_true = PL_new_atom("true"); - // ATOM_false = PL_new_atom("false"); + ATOM_true = PL_new_atom("true"); + ATOM_false = PL_new_atom("false"); PL_register_foreign("init_python", 0, init_python, 0); PL_register_foreign("end_python", 0, end_python, 0); + PL_register_foreign("python_import", 2, python_import, 0); + PL_register_foreign("python_f", 3, python_f, 0); + PL_register_foreign("python_apply", 3, python_apply, 0); PL_register_foreign("python_run_command", 1, python_run_command, 0); } + diff --git a/packages/pyswip/python.pl b/packages/pyswip/python.pl index f0d698992..8eb01576a 100644 --- a/packages/pyswip/python.pl +++ b/packages/pyswip/python.pl @@ -1,20 +1,33 @@ %%% -*- Mode: Prolog; -*- %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Author: Nicos Angelopoulos, Vitor Santos Costa, Jan Wielemaker -% E-mail: Nicos Angelopoulos -% Copyright (C): Nicos Angelopoulos, Universidade do Porto, VU University Amsterdam +% Author: Vitor Santos Costa +% E-mail: vsc@dcc.fc.up.pt +% Copyright (C): Universidade do Porto %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % -% This file is part of r..eal +% This file is part of the YAP Python Interface % distributed according to Perl Artistic License % check LICENSE file for distribution license % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +/** python + +A C-based Prolog interface to python. + +@author Vitor Santos Costa +@version 0:0:5, 2012/10/8 +@license Perl Artistic License + +*/ + +%%% + :- module(python, [ init_python/0, end_python/0, - python_command/1 + python_command/1, + python/3 ]). :- use_module(library(shlib)). @@ -22,18 +35,11 @@ :- use_module(library(apply_macros)). :- use_module(library(charsio)). -/** python - -A C-based Prolog interface to python. - - -@author Vitor Santos Costa -@version 0:0:5, 2012/09/12 -@license Perl Artistic License - -*/ - -%%% +python(Module:Function, IArgs, OArg) :- + python_import(Module, MRef), + python_f(MRef, Function, FRef), + Args =.. [c|IArgs], + python_apply(FRef, Args, OArg). python_command(Cmd) :- python_run_command(Cmd).