我正在向 Exim 添加一个嵌入式 python 解释器。我已经复制了嵌入式 perl 接口,并希望 python 与长期以来编码的嵌入式 perl 解释器一样工作。目标是允许系统管理员使用强大的脚本语言(即python)执行复杂的功能,而不是尝试使用exim 的标准ACL 命令,因为使用exim ACL 语言执行相对简单的事情会变得相当复杂。
在撰写本文时,我当前的代码位于http://git.exim.org/users/tlyons/exim.git/blob/9b2c5e1427d3861a2154bba04ac9b1f2420908f7:/src/src/python.c。它可以正常工作,因为它可以导入系统管理员的自定义 python 代码,调用其中的函数,并处理返回值(仅限简单返回类型:int、float 或 string)。但是,它还没有处理传递给 python 函数的值,这是我的问题开始的地方。
Python 似乎要求使用 c api 将我传递给嵌入式 python 函数的任何参数显式转换为 int、long、double、float 或 string 之一。问题是系统管理员可以在嵌入的 python 代码和 exim 的 c 方面放入任何东西,我不知道这些变量类型是什么。我知道 python 是动态类型的,所以我希望在将值传递给嵌入式代码时保持这种合规性。但在我的测试中它不是这样工作的。
使用以下基本的超简单 python 代码:
def dumb_add(a,b):
return a+b
...而我的 exim ACL 语言的调用代码是:
${python {dumb_add}{800}{100}}
在下面的 c 代码中,为简洁起见,省略了引用计数。 count是我传递的参数数量:
pArgs = PyTuple_New(count);
for (i=0; i<count; ++i)
{
pValue = PyString_FromString((const char *)arg[i]);
PyTuple_SetItem(pArgs, i, pValue);
}
pReturn = PyObject_CallObject(pFunc, pArgs);
是的,**arg 是一个指向字符串数组的指针(在这个简单的例子中是两个字符串)。问题是这两个值在 python 代码中被视为字符串,因此该 c 代码执行嵌入式 python 的结果是:
${python {dumb_add}{800}{100}}
800100
如果我将python更改为:
def dumb_add(a,b):
return int(a)+int(b)
然后该 c 代码执行 python 代码的结果与预期的一样:
${python {dumb_add}{800}{100}}
900
我的目标是我不想强迫 python 用户手动将他们传递给嵌入式 python 函数的所有数字参数强制转换。如果有一个 PyDynamicType_FromString(),而不是 PyString_FromString(),我会欣喜若狂。Exim 的嵌入式 perl 解析 args 并自动进行转换,我希望嵌入式 python 也能做到这一点。任何人都可以建议 python 是否可以执行此 arg 解析以提供我期望的动态类型?
或者,如果我想保持这种动态类型,我唯一的选择是解析每个 arg 并猜测将其转换为的类型吗?我真的真的真的很希望避免这种方法。如果涉及到这一点,我可能只是记录“所有传递的参数都是字符串,所以如果你真的想传递数字,你必须用 int()、float()、double() 或 long() 转换所有参数” . 然而,后面总是有一个逗号,我觉得这种方法会使我的实现中强大的 python 编码器变得糟糕。我也想避免这种情况。
除了“将您的应用程序变成 python 模块”之外,任何和所有建议都将受到赞赏。