mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 01:12:13 +00:00
Initial Python integration support. Disabled by default, find and
change the setting of HAVE_PYTHON in build.jam to enable it. [SVN r27559]
This commit is contained in:
@@ -17,6 +17,11 @@ VERSION = 3$(.)1$(.)10 ;
|
||||
RELEASE = 1 ;
|
||||
LICENSE = 1_0 ;
|
||||
|
||||
HAVE_PYTHON = 0 ;
|
||||
PYTHON_INCUDES = /usr/include/python2.3 ;
|
||||
PYTHON_LIB = -lpython2.3 ;
|
||||
|
||||
|
||||
# Generate development debug binaries?
|
||||
if --debug in $(ARGV)
|
||||
{
|
||||
@@ -326,6 +331,16 @@ if $(VMS)
|
||||
}
|
||||
--defs += YYSTACKSIZE=5000 ;
|
||||
|
||||
if $(HAVE_PYTHON) = 1
|
||||
{
|
||||
--defs += HAVE_PYTHON ;
|
||||
--flags += -I$(PYTHON_INCUDES) ;
|
||||
--flags += -Wno-long-long ;
|
||||
--libs += $(PYTHON_LIB) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# The basic symbolic targets...
|
||||
NOTFILE all clean dist ;
|
||||
ALWAYS clean ;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
# include "hdrmacro.h"
|
||||
# include "compile.h"
|
||||
# include "native.h"
|
||||
# include "variable.h"
|
||||
# include <ctype.h>
|
||||
|
||||
/*
|
||||
@@ -287,8 +288,14 @@ load_builtins()
|
||||
builtin_check_if_file, 0, args );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
{
|
||||
char * args[] = { "python-module", ":", "function", ":",
|
||||
"jam-module", ":", "rule-name", 0 };
|
||||
bind_builtin( "PYTHON_IMPORT_RULE",
|
||||
builtin_python_import_rule, 0, args );
|
||||
}
|
||||
#endif
|
||||
|
||||
# ifdef OS_NT
|
||||
{
|
||||
@@ -1238,6 +1245,92 @@ LIST *builtin_check_if_file( PARSE *parse, FRAME *frame )
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame )
|
||||
{
|
||||
static int first_time = 1;
|
||||
char* python_module = lol_get( frame->args, 0 )->string;
|
||||
char* python_function = lol_get( frame->args, 1 )->string;
|
||||
char* jam_module = lol_get( frame->args, 2 )->string;
|
||||
char* jam_rule = lol_get( frame->args, 3 )->string;
|
||||
|
||||
PyObject *pName, *pModule, *pDict, *pFunc;
|
||||
|
||||
if (first_time)
|
||||
{
|
||||
/* At the first invocation, we add the value of the
|
||||
global EXTRA_PYTHONPATH to the sys.path Python
|
||||
variable.
|
||||
*/
|
||||
LIST* extra = 0;
|
||||
module_t* outer_module = frame->module;
|
||||
|
||||
first_time = 0;
|
||||
|
||||
if ( outer_module != root_module())
|
||||
{
|
||||
exit_module( outer_module );
|
||||
enter_module( root_module());
|
||||
}
|
||||
|
||||
extra = var_get("EXTRA_PYTHONPATH");
|
||||
|
||||
if ( outer_module != root_module())
|
||||
{
|
||||
exit_module( root_module());
|
||||
enter_module( outer_module );
|
||||
}
|
||||
|
||||
for(; extra; extra = extra->next)
|
||||
{
|
||||
string buf[1];
|
||||
string_new(buf);
|
||||
string_append(buf, "import sys\nsys.path.append(\"");
|
||||
string_append(buf, extra->string);
|
||||
string_append(buf, "\")\n");
|
||||
PyRun_SimpleString(buf->value);
|
||||
string_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pName = PyString_FromString(python_module);
|
||||
|
||||
pModule = PyImport_Import(pName);
|
||||
Py_DECREF(pName);
|
||||
|
||||
if (pModule != NULL) {
|
||||
pDict = PyModule_GetDict(pModule);
|
||||
pFunc = PyDict_GetItemString(pDict, python_function);
|
||||
|
||||
if (pFunc && PyCallable_Check(pFunc)) {
|
||||
|
||||
module_t* m = bindmodule(jam_module);
|
||||
RULE* r = bindrule( jam_rule, m );
|
||||
|
||||
/* Make pFunc owned */
|
||||
Py_INCREF(pFunc);
|
||||
|
||||
r->python_function = pFunc;
|
||||
}
|
||||
else {
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
fprintf(stderr, "Cannot find function \"%s\"\n", python_function);
|
||||
}
|
||||
Py_DECREF(pModule);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
fprintf(stderr, "Failed to load \"%s\"\n", python_module);
|
||||
}
|
||||
return L0;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void lol_build( LOL* lol, char** elements )
|
||||
{
|
||||
LIST* l = L0;
|
||||
@@ -1261,3 +1354,92 @@ void lol_build( LOL* lol, char** elements )
|
||||
lol_add( lol, l );
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
/** Calls the bjam rule specified by name passed in 'args'.
|
||||
The name is looked up in context of bjam's 'python_interface'
|
||||
module. Returns the list of string retured by the rule.
|
||||
*/
|
||||
PyObject*
|
||||
bjam_call(PyObject* self, PyObject* args)
|
||||
{
|
||||
FRAME inner[1];
|
||||
LIST *result;
|
||||
PARSE *p;
|
||||
char* rulename;
|
||||
|
||||
/* Build up the list of arg lists */
|
||||
|
||||
frame_init( inner );
|
||||
inner->prev = 0;
|
||||
inner->prev_user = 0;
|
||||
inner->module = bindmodule("python_interface");
|
||||
inner->procedure = 0;
|
||||
|
||||
/* Extract the rule name and arguments from 'args' */
|
||||
|
||||
/* PyTuple_GetItem returns borrowed reference */
|
||||
rulename = PyString_AsString(PyTuple_GetItem(args, 0));
|
||||
{
|
||||
int i = 1;
|
||||
int size = PyTuple_Size(args);
|
||||
for( ; i < size; ++i) {
|
||||
PyObject* a = PyTuple_GetItem(args, i);
|
||||
if (PyString_Check(a))
|
||||
{
|
||||
lol_add(inner->args,
|
||||
list_new(0, newstr(PyString_AsString(a))));
|
||||
}
|
||||
else if (PySequence_Check(a))
|
||||
{
|
||||
LIST* l = 0;
|
||||
int s = PySequence_Size(a);
|
||||
int i = 0;
|
||||
for(; i < s; ++i)
|
||||
{
|
||||
/* PySequence_GetItem returns new reference. */
|
||||
PyObject* e = PySequence_GetItem(a, i);
|
||||
l = list_new(l, newstr(PyString_AsString(e)));
|
||||
Py_DECREF(e);
|
||||
}
|
||||
lol_add(inner->args, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = evaluate_rule( rulename, inner );
|
||||
|
||||
frame_free( inner );
|
||||
}
|
||||
|
||||
/** Accepts three arguments: module name, rule name and Python callable.
|
||||
|
||||
Creates bjam rule with the specified name in the specified module,
|
||||
which will invoke the Python callable.
|
||||
*/
|
||||
PyObject*
|
||||
bjam_import_rule(PyObject* self, PyObject* args)
|
||||
{
|
||||
char* module;
|
||||
char* rule;
|
||||
PyObject* func;
|
||||
module_t* m;
|
||||
RULE* r;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func))
|
||||
return NULL;
|
||||
|
||||
if (!PyCallable_Check(func))
|
||||
return NULL;
|
||||
|
||||
m = bindmodule(module);
|
||||
r = bindrule(rule, m);
|
||||
|
||||
/* Make pFunc owned */
|
||||
Py_INCREF(func);
|
||||
|
||||
r->python_function = func;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,6 +44,7 @@ LIST *builtin_native_rule( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_user_module( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_check_if_file( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame );
|
||||
|
||||
void backtrace( FRAME *frame );
|
||||
|
||||
|
||||
@@ -889,6 +889,106 @@ void profile_dump()
|
||||
}
|
||||
}
|
||||
|
||||
static int python_instance_number = 0;
|
||||
|
||||
RULE *
|
||||
enter_rule( char *rulename, module_t *target_module );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
static LIST*
|
||||
call_python_function(RULE* r, FRAME* frame)
|
||||
{
|
||||
LIST* result = 0;
|
||||
PyObject* arguments = PyTuple_New(frame->args->count);
|
||||
int i ;
|
||||
PyObject* py_result;
|
||||
|
||||
for(i = 0; i < frame->args->count; ++i)
|
||||
{
|
||||
PyObject* arg = PyList_New(0);
|
||||
LIST* l = lol_get( frame->args, i);
|
||||
|
||||
for(; l; l = l->next)
|
||||
{
|
||||
PyObject* v = PyString_FromString(l->string);
|
||||
/* Steals reference to 'v' */
|
||||
PyList_Append(arg, v);
|
||||
}
|
||||
/* Steals reference to 'arg' */
|
||||
PyTuple_SetItem(arguments, i, arg);
|
||||
}
|
||||
|
||||
py_result = PyObject_CallObject(r->python_function, arguments);
|
||||
Py_DECREF(arguments);
|
||||
if (py_result != NULL) {
|
||||
|
||||
if (PyList_Check(py_result)) {
|
||||
int size = PyList_Size(py_result);
|
||||
int i;
|
||||
for(i = 0; i < size; ++i)
|
||||
{
|
||||
PyObject* item = PyList_GetItem(py_result, i);
|
||||
if (PyString_Check(item))
|
||||
{
|
||||
result = list_new(result,
|
||||
newstr(PyString_AsString(item)));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Non-string object returned by Python call\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PyInstance_Check(py_result))
|
||||
{
|
||||
static char instance_name[1000];
|
||||
static char imported_method_name[1000];
|
||||
module_t* m;
|
||||
PyObject* method;
|
||||
PyObject* method_name = PyString_FromString("foo");
|
||||
RULE* r;
|
||||
|
||||
fprintf(stderr, "Got instance!\n");
|
||||
|
||||
snprintf(instance_name, 1000,
|
||||
"pyinstance%d", python_instance_number);
|
||||
snprintf(imported_method_name, 1000,
|
||||
"pyinstance%d.foo", python_instance_number);
|
||||
++python_instance_number;
|
||||
|
||||
m = bindmodule(instance_name);
|
||||
|
||||
/* This is expected to get bound method. */
|
||||
method = PyObject_GetAttr(py_result, method_name);
|
||||
|
||||
r = bindrule( imported_method_name, root_module() );
|
||||
|
||||
r->python_function = method;
|
||||
|
||||
result = list_new(0, newstr(instance_name));
|
||||
|
||||
Py_DECREF(method_name);
|
||||
}
|
||||
else if (py_result == Py_None)
|
||||
{
|
||||
result = L0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Non-list object returned by Python call\n");
|
||||
}
|
||||
|
||||
Py_DECREF(py_result);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
fprintf(stderr,"Call failed\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* evaluate_rule() - execute a rule invocation
|
||||
*/
|
||||
@@ -925,6 +1025,13 @@ evaluate_rule(
|
||||
rulename = l->string;
|
||||
rule = bindrule( l->string, frame->module );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
if (rule->python_function)
|
||||
{
|
||||
return call_python_function(rule, frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* drop the rule name */
|
||||
l = list_pop_front( l );
|
||||
|
||||
|
||||
@@ -196,6 +196,14 @@ static void run_unit_tests()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
extern PyObject*
|
||||
bjam_call(PyObject *self, PyObject *args);
|
||||
|
||||
extern PyObject*
|
||||
bjam_import_rule(PyObject* self, PyObject* args);
|
||||
#endif
|
||||
|
||||
int main( int argc, char **argv, char **arg_environ )
|
||||
{
|
||||
int n;
|
||||
@@ -211,6 +219,23 @@ int main( int argc, char **argv, char **arg_environ )
|
||||
InitGraf(&qd.thePort);
|
||||
# endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
Py_Initialize();
|
||||
|
||||
{
|
||||
static PyMethodDef BjamMethods[] = {
|
||||
{"call", bjam_call, METH_VARARGS,
|
||||
"Call the specified bjam rule."},
|
||||
{"import_rule", bjam_import_rule, METH_VARARGS,
|
||||
"Imports Python callable to bjam."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
Py_InitModule("bjam", BjamMethods);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
argc--, argv++;
|
||||
|
||||
if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 )
|
||||
@@ -463,5 +488,10 @@ int main( int argc, char **argv, char **arg_environ )
|
||||
if( globs.cmdout )
|
||||
fclose( globs.cmdout );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
Py_Finalize();
|
||||
#endif
|
||||
|
||||
|
||||
return status ? EXITBAD : EXITOK;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
|
||||
#ifndef JAM_H_VP_2003_08_01
|
||||
#define JAM_H_VP_2003_08_01
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* VMS, OPENVMS
|
||||
*/
|
||||
|
||||
@@ -82,6 +82,9 @@ enter_rule( char *rulename, module_t *target_module )
|
||||
r->arguments = 0;
|
||||
r->exported = 0;
|
||||
r->module = target_module;
|
||||
#ifdef HAVE_PYTHON
|
||||
r->python_function = 0;
|
||||
#endif
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,9 @@ struct _rule {
|
||||
* appear in the global module and be
|
||||
* automatically imported into other modules
|
||||
*/
|
||||
#ifdef HAVE_PYTHON
|
||||
PyObject* python_function;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ACTIONS - a chain of ACTIONs */
|
||||
|
||||
@@ -17,6 +17,11 @@ VERSION = 3$(.)1$(.)10 ;
|
||||
RELEASE = 1 ;
|
||||
LICENSE = 1_0 ;
|
||||
|
||||
HAVE_PYTHON = 0 ;
|
||||
PYTHON_INCUDES = /usr/include/python2.3 ;
|
||||
PYTHON_LIB = -lpython2.3 ;
|
||||
|
||||
|
||||
# Generate development debug binaries?
|
||||
if --debug in $(ARGV)
|
||||
{
|
||||
@@ -326,6 +331,16 @@ if $(VMS)
|
||||
}
|
||||
--defs += YYSTACKSIZE=5000 ;
|
||||
|
||||
if $(HAVE_PYTHON) = 1
|
||||
{
|
||||
--defs += HAVE_PYTHON ;
|
||||
--flags += -I$(PYTHON_INCUDES) ;
|
||||
--flags += -Wno-long-long ;
|
||||
--libs += $(PYTHON_LIB) ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# The basic symbolic targets...
|
||||
NOTFILE all clean dist ;
|
||||
ALWAYS clean ;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
# include "hdrmacro.h"
|
||||
# include "compile.h"
|
||||
# include "native.h"
|
||||
# include "variable.h"
|
||||
# include <ctype.h>
|
||||
|
||||
/*
|
||||
@@ -287,8 +288,14 @@ load_builtins()
|
||||
builtin_check_if_file, 0, args );
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
{
|
||||
char * args[] = { "python-module", ":", "function", ":",
|
||||
"jam-module", ":", "rule-name", 0 };
|
||||
bind_builtin( "PYTHON_IMPORT_RULE",
|
||||
builtin_python_import_rule, 0, args );
|
||||
}
|
||||
#endif
|
||||
|
||||
# ifdef OS_NT
|
||||
{
|
||||
@@ -1238,6 +1245,92 @@ LIST *builtin_check_if_file( PARSE *parse, FRAME *frame )
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame )
|
||||
{
|
||||
static int first_time = 1;
|
||||
char* python_module = lol_get( frame->args, 0 )->string;
|
||||
char* python_function = lol_get( frame->args, 1 )->string;
|
||||
char* jam_module = lol_get( frame->args, 2 )->string;
|
||||
char* jam_rule = lol_get( frame->args, 3 )->string;
|
||||
|
||||
PyObject *pName, *pModule, *pDict, *pFunc;
|
||||
|
||||
if (first_time)
|
||||
{
|
||||
/* At the first invocation, we add the value of the
|
||||
global EXTRA_PYTHONPATH to the sys.path Python
|
||||
variable.
|
||||
*/
|
||||
LIST* extra = 0;
|
||||
module_t* outer_module = frame->module;
|
||||
|
||||
first_time = 0;
|
||||
|
||||
if ( outer_module != root_module())
|
||||
{
|
||||
exit_module( outer_module );
|
||||
enter_module( root_module());
|
||||
}
|
||||
|
||||
extra = var_get("EXTRA_PYTHONPATH");
|
||||
|
||||
if ( outer_module != root_module())
|
||||
{
|
||||
exit_module( root_module());
|
||||
enter_module( outer_module );
|
||||
}
|
||||
|
||||
for(; extra; extra = extra->next)
|
||||
{
|
||||
string buf[1];
|
||||
string_new(buf);
|
||||
string_append(buf, "import sys\nsys.path.append(\"");
|
||||
string_append(buf, extra->string);
|
||||
string_append(buf, "\")\n");
|
||||
PyRun_SimpleString(buf->value);
|
||||
string_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pName = PyString_FromString(python_module);
|
||||
|
||||
pModule = PyImport_Import(pName);
|
||||
Py_DECREF(pName);
|
||||
|
||||
if (pModule != NULL) {
|
||||
pDict = PyModule_GetDict(pModule);
|
||||
pFunc = PyDict_GetItemString(pDict, python_function);
|
||||
|
||||
if (pFunc && PyCallable_Check(pFunc)) {
|
||||
|
||||
module_t* m = bindmodule(jam_module);
|
||||
RULE* r = bindrule( jam_rule, m );
|
||||
|
||||
/* Make pFunc owned */
|
||||
Py_INCREF(pFunc);
|
||||
|
||||
r->python_function = pFunc;
|
||||
}
|
||||
else {
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
fprintf(stderr, "Cannot find function \"%s\"\n", python_function);
|
||||
}
|
||||
Py_DECREF(pModule);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
fprintf(stderr, "Failed to load \"%s\"\n", python_module);
|
||||
}
|
||||
return L0;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void lol_build( LOL* lol, char** elements )
|
||||
{
|
||||
LIST* l = L0;
|
||||
@@ -1261,3 +1354,92 @@ void lol_build( LOL* lol, char** elements )
|
||||
lol_add( lol, l );
|
||||
}
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
/** Calls the bjam rule specified by name passed in 'args'.
|
||||
The name is looked up in context of bjam's 'python_interface'
|
||||
module. Returns the list of string retured by the rule.
|
||||
*/
|
||||
PyObject*
|
||||
bjam_call(PyObject* self, PyObject* args)
|
||||
{
|
||||
FRAME inner[1];
|
||||
LIST *result;
|
||||
PARSE *p;
|
||||
char* rulename;
|
||||
|
||||
/* Build up the list of arg lists */
|
||||
|
||||
frame_init( inner );
|
||||
inner->prev = 0;
|
||||
inner->prev_user = 0;
|
||||
inner->module = bindmodule("python_interface");
|
||||
inner->procedure = 0;
|
||||
|
||||
/* Extract the rule name and arguments from 'args' */
|
||||
|
||||
/* PyTuple_GetItem returns borrowed reference */
|
||||
rulename = PyString_AsString(PyTuple_GetItem(args, 0));
|
||||
{
|
||||
int i = 1;
|
||||
int size = PyTuple_Size(args);
|
||||
for( ; i < size; ++i) {
|
||||
PyObject* a = PyTuple_GetItem(args, i);
|
||||
if (PyString_Check(a))
|
||||
{
|
||||
lol_add(inner->args,
|
||||
list_new(0, newstr(PyString_AsString(a))));
|
||||
}
|
||||
else if (PySequence_Check(a))
|
||||
{
|
||||
LIST* l = 0;
|
||||
int s = PySequence_Size(a);
|
||||
int i = 0;
|
||||
for(; i < s; ++i)
|
||||
{
|
||||
/* PySequence_GetItem returns new reference. */
|
||||
PyObject* e = PySequence_GetItem(a, i);
|
||||
l = list_new(l, newstr(PyString_AsString(e)));
|
||||
Py_DECREF(e);
|
||||
}
|
||||
lol_add(inner->args, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result = evaluate_rule( rulename, inner );
|
||||
|
||||
frame_free( inner );
|
||||
}
|
||||
|
||||
/** Accepts three arguments: module name, rule name and Python callable.
|
||||
|
||||
Creates bjam rule with the specified name in the specified module,
|
||||
which will invoke the Python callable.
|
||||
*/
|
||||
PyObject*
|
||||
bjam_import_rule(PyObject* self, PyObject* args)
|
||||
{
|
||||
char* module;
|
||||
char* rule;
|
||||
PyObject* func;
|
||||
module_t* m;
|
||||
RULE* r;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ssO:import_rule", &module, &rule, &func))
|
||||
return NULL;
|
||||
|
||||
if (!PyCallable_Check(func))
|
||||
return NULL;
|
||||
|
||||
m = bindmodule(module);
|
||||
r = bindrule(rule, m);
|
||||
|
||||
/* Make pFunc owned */
|
||||
Py_INCREF(func);
|
||||
|
||||
r->python_function = func;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -44,6 +44,7 @@ LIST *builtin_native_rule( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_user_module( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_nearest_user_location( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_check_if_file( PARSE *parse, FRAME *frame );
|
||||
LIST *builtin_python_import_rule( PARSE *parse, FRAME *frame );
|
||||
|
||||
void backtrace( FRAME *frame );
|
||||
|
||||
|
||||
@@ -889,6 +889,106 @@ void profile_dump()
|
||||
}
|
||||
}
|
||||
|
||||
static int python_instance_number = 0;
|
||||
|
||||
RULE *
|
||||
enter_rule( char *rulename, module_t *target_module );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
static LIST*
|
||||
call_python_function(RULE* r, FRAME* frame)
|
||||
{
|
||||
LIST* result = 0;
|
||||
PyObject* arguments = PyTuple_New(frame->args->count);
|
||||
int i ;
|
||||
PyObject* py_result;
|
||||
|
||||
for(i = 0; i < frame->args->count; ++i)
|
||||
{
|
||||
PyObject* arg = PyList_New(0);
|
||||
LIST* l = lol_get( frame->args, i);
|
||||
|
||||
for(; l; l = l->next)
|
||||
{
|
||||
PyObject* v = PyString_FromString(l->string);
|
||||
/* Steals reference to 'v' */
|
||||
PyList_Append(arg, v);
|
||||
}
|
||||
/* Steals reference to 'arg' */
|
||||
PyTuple_SetItem(arguments, i, arg);
|
||||
}
|
||||
|
||||
py_result = PyObject_CallObject(r->python_function, arguments);
|
||||
Py_DECREF(arguments);
|
||||
if (py_result != NULL) {
|
||||
|
||||
if (PyList_Check(py_result)) {
|
||||
int size = PyList_Size(py_result);
|
||||
int i;
|
||||
for(i = 0; i < size; ++i)
|
||||
{
|
||||
PyObject* item = PyList_GetItem(py_result, i);
|
||||
if (PyString_Check(item))
|
||||
{
|
||||
result = list_new(result,
|
||||
newstr(PyString_AsString(item)));
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Non-string object returned by Python call\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (PyInstance_Check(py_result))
|
||||
{
|
||||
static char instance_name[1000];
|
||||
static char imported_method_name[1000];
|
||||
module_t* m;
|
||||
PyObject* method;
|
||||
PyObject* method_name = PyString_FromString("foo");
|
||||
RULE* r;
|
||||
|
||||
fprintf(stderr, "Got instance!\n");
|
||||
|
||||
snprintf(instance_name, 1000,
|
||||
"pyinstance%d", python_instance_number);
|
||||
snprintf(imported_method_name, 1000,
|
||||
"pyinstance%d.foo", python_instance_number);
|
||||
++python_instance_number;
|
||||
|
||||
m = bindmodule(instance_name);
|
||||
|
||||
/* This is expected to get bound method. */
|
||||
method = PyObject_GetAttr(py_result, method_name);
|
||||
|
||||
r = bindrule( imported_method_name, root_module() );
|
||||
|
||||
r->python_function = method;
|
||||
|
||||
result = list_new(0, newstr(instance_name));
|
||||
|
||||
Py_DECREF(method_name);
|
||||
}
|
||||
else if (py_result == Py_None)
|
||||
{
|
||||
result = L0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Non-list object returned by Python call\n");
|
||||
}
|
||||
|
||||
Py_DECREF(py_result);
|
||||
}
|
||||
else {
|
||||
PyErr_Print();
|
||||
fprintf(stderr,"Call failed\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* evaluate_rule() - execute a rule invocation
|
||||
*/
|
||||
@@ -925,6 +1025,13 @@ evaluate_rule(
|
||||
rulename = l->string;
|
||||
rule = bindrule( l->string, frame->module );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
if (rule->python_function)
|
||||
{
|
||||
return call_python_function(rule, frame);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* drop the rule name */
|
||||
l = list_pop_front( l );
|
||||
|
||||
|
||||
@@ -196,6 +196,14 @@ static void run_unit_tests()
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
extern PyObject*
|
||||
bjam_call(PyObject *self, PyObject *args);
|
||||
|
||||
extern PyObject*
|
||||
bjam_import_rule(PyObject* self, PyObject* args);
|
||||
#endif
|
||||
|
||||
int main( int argc, char **argv, char **arg_environ )
|
||||
{
|
||||
int n;
|
||||
@@ -211,6 +219,23 @@ int main( int argc, char **argv, char **arg_environ )
|
||||
InitGraf(&qd.thePort);
|
||||
# endif
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
Py_Initialize();
|
||||
|
||||
{
|
||||
static PyMethodDef BjamMethods[] = {
|
||||
{"call", bjam_call, METH_VARARGS,
|
||||
"Call the specified bjam rule."},
|
||||
{"import_rule", bjam_import_rule, METH_VARARGS,
|
||||
"Imports Python callable to bjam."},
|
||||
{NULL, NULL, 0, NULL}
|
||||
};
|
||||
|
||||
Py_InitModule("bjam", BjamMethods);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
argc--, argv++;
|
||||
|
||||
if( ( n = getoptions( argc, argv, "-:d:j:f:gs:t:ano:qv", optv ) ) < 0 )
|
||||
@@ -463,5 +488,10 @@ int main( int argc, char **argv, char **arg_environ )
|
||||
if( globs.cmdout )
|
||||
fclose( globs.cmdout );
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
Py_Finalize();
|
||||
#endif
|
||||
|
||||
|
||||
return status ? EXITBAD : EXITOK;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,11 @@
|
||||
|
||||
#ifndef JAM_H_VP_2003_08_01
|
||||
#define JAM_H_VP_2003_08_01
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* VMS, OPENVMS
|
||||
*/
|
||||
|
||||
@@ -82,6 +82,9 @@ enter_rule( char *rulename, module_t *target_module )
|
||||
r->arguments = 0;
|
||||
r->exported = 0;
|
||||
r->module = target_module;
|
||||
#ifdef HAVE_PYTHON
|
||||
r->python_function = 0;
|
||||
#endif
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -87,6 +87,9 @@ struct _rule {
|
||||
* appear in the global module and be
|
||||
* automatically imported into other modules
|
||||
*/
|
||||
#ifdef HAVE_PYTHON
|
||||
PyObject* python_function;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ACTIONS - a chain of ACTIONs */
|
||||
|
||||
Reference in New Issue
Block a user