Python 如何编写一个接受int或float的C函数?

Python 如何编写一个接受int或float的C函数?,python,c,python-extensions,Python,C,Python Extensions,我想用C创建一个函数,它扩展了Python,可以接受浮点或int类型的输入。所以基本上,我希望f(5)和f(5.5)是可接受的输入 我认为如果(!PyArg_ParseTuple(args,“I”,$value))我不能使用,因为它只需要int或float 如何使函数允许输入为int或float 我想知道我是否应该将输入放入PyObject并以某种方式获取PyObject的类型-这是正确的方法吗?您可以像这样检查输入值的类型: PyObject* check_type(PyObject*

我想用C创建一个函数,它扩展了Python,可以接受浮点或int类型的输入。所以基本上,我希望
f(5)
f(5.5)
是可接受的输入

我认为如果(!PyArg_ParseTuple(args,“I”,$value))我不能使用
,因为它只需要int或float

如何使函数允许输入为int或float


我想知道我是否应该将输入放入PyObject并以某种方式获取PyObject的类型-这是正确的方法吗?

您可以像这样检查输入值的类型:

    PyObject* check_type(PyObject*self, PyObject*args) {
    PyObject*any;

    if (!PyArg_ParseTuple(args, "O", &any)) {
        PyErr_SetString(PyExc_TypeError, "Nope.");
        return NULL;
    }

    if (PyFloat_Check(any)) {
        printf("indeed float");
    }
    else {
        printf("\nint\n");
    }

    Py_INCREF(Py_None);

    return Py_None;
}
可以使用以下命令从对象提取浮点值:

double result=PyFloat_AsDouble(any);
但在这种特殊情况下,可能不需要这样做,无论您解析int还是float,都可以将其作为一个float抓取并检查圆度:

    float target;
    if (!PyArg_ParseTuple(args, "f", &target)) {
                PyErr_SetString(PyExc_TypeError, "Nope.");
                return NULL;
    }

    if (target - (int)target) {
        printf("\n input is float \n");
    }
    else {
        printf("\n input is int \n");
    }

如果您声明一个C函数接受浮点数,那么如果您给它一个int,编译器不会抱怨。例如,此程序生成的答案为2.000000:

#include <stdio.h>

float f(float x) {
  return x+1;
}

int main() {
  int i=1;
  printf ("%f", f(i));
}
例如:

03:21 $ python
Python 2.7.10 (default, Jul 30 2016, 18:31:42)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import iorf
>>> print iorf.fup(2)
3.0
>>> print iorf.fup(2.5)
3.5
浮点数(通常)通过寄存器传入,而整数(通常)通过堆栈传入。这意味着您实际上无法在函数内部检查参数是浮点还是int

唯一的解决方法是使用可变参数,第一个参数将类型指定为int或double(不是float)


尽管如此,我不确定python是否能够处理变量函数的调用,所以YMMV。作为最后的努力,您可以随时将值冲刺到缓冲区中,并让函数sscanf float/int从缓冲区中移出。

注意:我编辑了您的问题,使其更易于阅读。如果您不喜欢我更改的内容,请随意更改回来,因为这是您的问题,而不是我的问题。您可能希望使用
PyObject
,然后使用来处理数字。例如,如果您需要强制使用
浮点值
,您可以在
PyObject
上调用
PyNumber\u Float
。但这只是因为C编译器在调用函数之前将
int
转换为
Float
。这是一个问题吗?我不认为Python运行时也会这样做。然后问题仍然存在,对吗?OP仍然需要调用ParseTuple最多两次,一次用于参数是
int
对象的情况,一次用于
float
。问题似乎不在于你以后如何处理这些值。不。看看这个例子。我给它一个int和一个float,它给出了正确的答案。试试看。
from distutils.core import setup, Extension

module1 = Extension('iorf',
                    sources = ['iorf.c'])

setup (name = 'iorf',
       version = '0.1',
       description = 'This is a test package',
       ext_modules = [module1])
03:21 $ python
Python 2.7.10 (default, Jul 30 2016, 18:31:42)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import iorf
>>> print iorf.fup(2)
3.0
>>> print iorf.fup(2.5)
3.5
func_int_or_double (uint8_t type, ...) {
va_list ap;
va_start (ap, type);
int intarg;
double doublearg;
if (type==1) {
   intarg = va_arg (ap, int);
}
if (type==2) {
   doublearg = va_arg (ap, double);
}
va_end (ap);
// Your code goes here
}