exim - Dynamic arg types for a python function when embedding -
i adding exim embedded python interpreter. have copied embedded perl interface , expect python work same long-since-coded embedded perl interpreter. goal allow sysadmin complex functions in powerful scripting language (i.e. python) instead of trying use exim's standard acl commands because can quite complex relatively simple things using exim acl language.
my current code of time of writing located @ http://git.exim.org/users/tlyons/exim.git/blob/9b2c5e1427d3861a2154bba04ac9b1f2420908f7:/src/src/python.c . working in can import sysadmin's custom python code, call functions in it, , handle returned values (simple return types only: int, float, or string). however, not yet handle values passed python function, question begins.
python seems require args pass embedded python function explicitly cast 1 of int,long,double,float or string using c api. problem sysadmin can put in embedded python code , in c side of things in exim, won't know variable types are. know python dynamically typed hoping maintain compliance when passing values embedded code. it's not working way in testing.
using following basic super-simple python code:
def dumb_add(a,b): return a+b
...and calling code exim acl language is:
${python {dumb_add}{800}{100}}
in c code below, reference counting omitted brevity. count number of args i'm passing:
pargs = pytuple_new(count); (i=0; i<count; ++i) { pvalue = pystring_fromstring((const char *)arg[i]); pytuple_setitem(pargs, i, pvalue); } preturn = pyobject_callobject(pfunc, pargs);
yes, **arg pointer array of strings (two strings in simple case). problem 2 values treated strings in python code, result of c code executing embedded python is:
${python {dumb_add}{800}{100}} 800100
if change python be:
def dumb_add(a,b): return int(a)+int(b)
then result of c code executing python code expected:
${python {dumb_add}{800}{100}} 900
my goal don't want force python user manually cast of numeric parameters pass embedded python function. instead of pystring_fromstring(), if there pydynamictype_fromstring(), ecstatic. exim's embedded perl parses args , casting automatically, hoping same embedded python. can suggest if python can arg parsing provide dynamic typing expecting?
or if want maintain dynamic typing, option going me parse each arg , guess @ type cast to? really hoping avoid approach. if comes that, may document "all parameters passed strings, if trying pass numbers, must cast parameters int(), float(), double(), or long()". however, , there comma after however, feel approach sour strong python coders on implementation. want avoid too.
any , suggestions appreciated, aside "make app python module".
the way ended solving finding out how many args function expected, , exit error if number of args passed function didn't match. rather try , synthesize missing args or omit args, use case felt best enforce matching arg counts.
the args passed function unsigned char ** arg
:
int count = 0; /* identify , call appropriate function */ pfunc = pyobject_getattrstring(pmodule, (const char *) name); if (pfunc && pycallable_check(pfunc)) { pycodeobject *pfunccode = (pycodeobject *)pyfunction_get_code(pfunc); /* should not fail if pfunc succeeded, check thorough */ if (!pfunccode) { *errstrp = string_sprintf("can't check function arg count %s", name); return null; } while(arg[count]) count++; /* sanity checking: calling python object requires state number of vars being passed, bail if doesn't match function declaration. */ if (count != pfunccode->co_argcount) { *errstrp = string_sprintf("expected %d args %s, passed %d", pfunccode->co_argcount, name, count); return null; }
the string_sprintf
function within exim source code handles memory allocation, making life easy me.
Comments
Post a Comment