improve interface

This commit is contained in:
Vítor Santos Costa 2012-10-17 10:56:44 +01:00
parent f753bce4fe
commit fb2a17addf
2 changed files with 190 additions and 19 deletions

View File

@ -1,8 +1,13 @@
#include <SWI-Stream.h>
#include <SWI-Prolog.h>
#ifdef HAVE_STAT
#undef HAVE_STAT
#endif
#include <Python.h>
#include <assert.h>
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);
}

View File

@ -1,20 +1,33 @@
%%% -*- Mode: Prolog; -*-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Author: Nicos Angelopoulos, Vitor Santos Costa, Jan Wielemaker
% E-mail: Nicos Angelopoulos <nicos@gmx.co.uk>
% 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
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/** <module> 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)).
/** <module> 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).