【发布时间】:2013-05-21 18:45:35
【问题描述】:
我正在向 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 解析以提供我期望的动态类型?
或者,如果我想保持这种动态类型,我唯一的选择是让 me 解析每个 arg 并猜测将其转换为的类型吗?我真的真的真的很希望避免这种方法。如果涉及到这一点,我可能只是记录“所有传递的参数都是字符串,所以如果你真的想传递数字,你必须用 int()、float()、double() 或 long() 转换所有参数” .然而,后面总是有一个逗号,我觉得这种方法会使我的实现中强大的 python 编码器变得糟糕。我也想避免这种情况。
除了“将你的应用程序变成一个 python 模块”之外,任何和所有建议都值得赞赏。
【问题讨论】:
-
你试过用PyRun_String代替PyString_FromString吗?
-
PyRun_String 如果只调用一个函数就足够了。但期望系统管理员可以定义 1、5、20 个函数,无论他需要多少,并随时从 Exim ACL 调用它们以用于各种目的。
-
我的评论只是为了解决动态类型。因此,在您的
dumb_add示例中,800 和 100 将使用pValue = PyRun_String((const char *)arg[i],...);之类的东西转换为 PyObjects。在这种情况下,arg[i] 将是“800”或“600”。因此,您正在“运行”字符串“800”,它应该返回一个整数类型的 PyObject。这有意义吗?
标签: python-c-api exim python-embedding