簡體   English   中英

如何編寫一個帶有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。

如何使我的函數允許輸入為int或float?

我想知道我是否應該只接受輸入並將其放入PyObject並以某種方式采用PyObject的類型 - 這是正確的方法嗎?

如果你聲明一個C函數來接受浮點數,那么如果你把它交給一個int,編譯器就不會抱怨。 例如,該程序產生答案2.000000:

#include <stdio.h>

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

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

一個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

您可以像這樣檢查輸入值的類型:

    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 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");
    }

浮點數(通常)通過寄存器傳入,而int(通常)通過堆棧傳入。 這意味着你在函數內部實際上不能檢查參數是float還是int。

唯一的解決方法是使用可變參數,第一個參數將類型指定為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從緩沖區中浮動/ int。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM