From 9718e10c7f4151cea895f515c785c14e0021d967 Mon Sep 17 00:00:00 2001 From: cbdev Date: Wed, 18 Mar 2020 22:36:35 +0100 Subject: Implement default channel handlers for Lua/Python --- backends/python.c | 65 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 20 deletions(-) (limited to 'backends/python.c') diff --git a/backends/python.c b/backends/python.c index 70c2548..735e838 100644 --- a/backends/python.c +++ b/backends/python.c @@ -378,6 +378,11 @@ static int python_configure_instance(instance* inst, char* option, char* value){ PyEval_ReleaseThread(data->interpreter); return 0; } + else if(!strcmp(option, "default-handler")){ + free(data->default_handler); + data->default_handler = strdup(value); + return 0; + } LOGPF("Unknown instance parameter %s for instance %s", option, inst->name); return 1; @@ -600,38 +605,56 @@ static int python_handle(size_t num, managed_fd* fds){ return 0; } +static PyObject* python_resolve_symbol(char* spec_raw){ + char* module_name = NULL, *object_name = NULL, *spec = strdup(spec_raw); + PyObject* module = NULL, *result = NULL; + + module = PyImport_AddModule("__main__"); + object_name = spec; + module_name = strchr(object_name, '.'); + if(module_name){ + *module_name = 0; + //returns borrowed reference + module = PyImport_AddModule(object_name); + + if(!module){ + LOGPF("Module %s for symbol %s.%s is not loaded", object_name, object_name, module_name + 1); + return NULL; + } + + object_name = module_name + 1; + + //returns new reference + result = PyObject_GetAttrString(module, object_name); + } + + free(spec); + return result; +} + static int python_start(size_t n, instance** inst){ python_instance_data* data = NULL; - PyObject* module = NULL; size_t u, p; - char* module_name = NULL, *channel_name = NULL; //resolve channel references to handler functions for(u = 0; u < n; u++){ data = (python_instance_data*) inst[u]->impl; + DBGPF("Starting up instance %s", inst[u]->name); //switch to interpreter PyEval_RestoreThread(data->interpreter); - for(p = 0; p < data->channels; p++){ - module = PyImport_AddModule("__main__"); - channel_name = data->channel[p].name; - module_name = strchr(channel_name, '.'); - if(module_name){ - *module_name = 0; - //returns borrowed reference - module = PyImport_AddModule(channel_name); - - if(!module){ - LOGPF("Module %s for qualified channel %s.%s is not loaded on instance %s", channel_name, channel_name, module_name + 1, inst[u]->name); - return 1; - } - *module_name = '.'; - channel_name = module_name + 1; - } + if(data->default_handler){ + data->handler = python_resolve_symbol(data->default_handler); + } - //returns new reference - data->channel[p].handler = PyObject_GetAttrString(module, channel_name); + for(p = 0; p < data->channels; p++){ + if(!strchr(data->channel[p].name, '.') && data->handler){ + data->channel[p].handler = data->handler; + } + else{ + data->channel[p].handler = python_resolve_symbol(data->channel[p].name); + } } //release interpreter @@ -654,6 +677,7 @@ static int python_shutdown(size_t n, instance** inst){ Py_XDECREF(data->channel[p].handler); } free(data->channel); + free(data->default_handler); //do not free data here, needed for shutting down interpreters } @@ -675,6 +699,7 @@ static int python_shutdown(size_t n, instance** inst){ for(p = 0; p handler); DBGPF("Shutting down interpreter for instance %s", inst[u]->name); //swap to interpreter and end it, GIL is held after this but state is NULL -- cgit v1.2.3