如何编写一个接受 int 或 float 的 C 函数?
How can I write a C function that takes either an int or a float?
我想在 C 中创建一个扩展 Python 的函数,它可以接受 float 或 int 类型的输入。所以基本上,我希望 f(5)
和 f(5.5)
是可以接受的输入。
我认为我不能使用 if (!PyArg_ParseTuple(args, "i", $value))
因为它只需要 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));
}
A python 模块版本,iorf.c:
#include <Python.h>
static PyObject *IorFError;
float f(float x) {
return x+1;
}
static PyObject *
fwrap(PyObject *self, PyObject *args) {
float in=0.0;
if (!PyArg_ParseTuple(args, "f", &in))
return NULL;
return Py_BuildValue("f", f(in));
}
static PyMethodDef IorFMethods[] = {
{"fup", fwrap, METH_VARARGS,
"Arg + 1"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initiorf(void)
{
PyObject *m;
m = Py_InitModule("iorf", IorFMethods);
if (m == NULL)
return;
IorFError = PyErr_NewException("iorf.error", NULL, NULL);
Py_INCREF(IorFError);
PyModule_AddObject(m, "error", IorFError);
}
setup.py:
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
浮点数(通常)通过寄存器传入,而整数(通常)通过堆栈传入。这意味着您实际上不能在函数内部检查参数是浮点数还是整数。
唯一的解决方法是使用可变参数,第一个参数将类型指定为 int 或 double(不是 float)。
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
}
虽然,我不太确定 python 是否可以处理调用可变参数函数,所以 YMMV。作为最后的努力,您始终可以将值 sprintf 放入缓冲区,然后让您的函数 sscanf float/int 从缓冲区中获取。
我想在 C 中创建一个扩展 Python 的函数,它可以接受 float 或 int 类型的输入。所以基本上,我希望 f(5)
和 f(5.5)
是可以接受的输入。
我认为我不能使用 if (!PyArg_ParseTuple(args, "i", $value))
因为它只需要 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));
}
A python 模块版本,iorf.c:
#include <Python.h>
static PyObject *IorFError;
float f(float x) {
return x+1;
}
static PyObject *
fwrap(PyObject *self, PyObject *args) {
float in=0.0;
if (!PyArg_ParseTuple(args, "f", &in))
return NULL;
return Py_BuildValue("f", f(in));
}
static PyMethodDef IorFMethods[] = {
{"fup", fwrap, METH_VARARGS,
"Arg + 1"},
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initiorf(void)
{
PyObject *m;
m = Py_InitModule("iorf", IorFMethods);
if (m == NULL)
return;
IorFError = PyErr_NewException("iorf.error", NULL, NULL);
Py_INCREF(IorFError);
PyModule_AddObject(m, "error", IorFError);
}
setup.py:
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
浮点数(通常)通过寄存器传入,而整数(通常)通过堆栈传入。这意味着您实际上不能在函数内部检查参数是浮点数还是整数。
唯一的解决方法是使用可变参数,第一个参数将类型指定为 int 或 double(不是 float)。
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
}
虽然,我不太确定 python 是否可以处理调用可变参数函数,所以 YMMV。作为最后的努力,您始终可以将值 sprintf 放入缓冲区,然后让您的函数 sscanf float/int 从缓冲区中获取。