相当于c的Cython定义#define myfunc(node x,...)SetNode(x.getattributeNode(),__ VA_ARGS__) [英] Cython equivalent of c define #define myfunc(node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)

查看:80
本文介绍了相当于c的Cython定义#define myfunc(node x,...)SetNode(x.getattributeNode(),__ VA_ARGS__)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Cython等效于c define

Cython equivalent of c define

#define myfunc(Node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)

我有一个ac api SetNode,它的第一个参数是结构类型为node的节点,并且为N个变量(N是从0到N的变量)

I have a c api SetNode which takes first argument a node of struct type node and N variables (N is variable number from 0-N)

这是解决此类问题的ac示例

here is a c example to solve such problum

exampleAPI。 c

exampleAPI.c

#include<stdarg.h>
float sumN(int len,...){
    va_list argp;
    int i;
    float s=0;
    va_start(argp,len);
    for(i=0;i<len;i++){
       s+=va_arg(argp,int);
    }
    va_end(argp);
}

exampleAPI.h

exampleAPI.h

#include<stdarg.h>
float sumN(int len,...)

examplecode.c

examplecode.c

#include<stdarg.h>
#include"exampleAPI.h"

int len(float first,...){
    va_list argp;
    int i=1;
    va_start(argp,first);
    while(1){
       if(va_arg(argp,float)==NULL){
            return i
       }
       else{
            i++;
       }
    }
    va_end(argp);
}

#define sum(...) sumN(len(__VA_ARGS__),__VA_ARGS__)

现在调用

sum(1,2,3,4);

将返回 10.000000

sum(1.5,6.5);

将返回 8.00000

我需要一个cython替代品用于下面的c定义,而不是上面的示例
,因为我有一个C-API,它具有SetNode函数,该函数需要可变数量的参数,并且我想将其包装在cython中并从python调用

I need a cython alternative for bellow c definition and not above example because I have a C-API which has SetNode function which takes variable number of arguments and I want to wrap it in cython and call from python

 #define myfunc(Node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)

其中Node是在cython中定义的类,该类将ac stuct作为属性,而getattributeNode()是Node类的函数,该函数返回

here Node is a class defined in cython which holds a c stuct as attribute and getattributeNode() is a function of Node class which returns c struct that needs to be passed into C-API.

cdef extern "Network.h":

    ctypedef struct node_bn:
         pass

    node_bn* SetNode(node_bn* node,...)


cdef class Node:

    cdef node_bn *node

    cdef getattributeNode(self):
        return self.node     

    def setNode(self,*arg):
        self.node=SetNode(self.node,*arg) # Error cannot convert python objects to c type

cdef extern from "stdarg.h":
   ctypedef struct va_list:
      pass
   ctypedef struct fake_type:
      pass
   void va_start(va_list, void* arg)
   void* va_arg(va_list, fake_type)
   void va_end(va_list)
   fake_type int_type "int" 

cdef extern "Network.h":

    ctypedef struct node_bn:
         pass

    node_bn* VSetNode(node_bn* node,va_list argp)


cdef class Node:

    cdef node_bn *node

    cdef getattributeNode(self):
        return self.node     

    cpdef _setNode(self,node_bn *node,...):
        cdef va_list agrp
        va_start(va_list, node)       
        self.node=VSetNode(node,argp) 
        va_end(va_list)

    def setNode(self,*arg):
        self._setNode(self.node,*arg) 

当参数列表为空时工作正常

works fine when argument list is empty

n = Node()
n.setNode() #This works
n.SetNode("top",1) # error takes exactly one argument given 3 in  self._setNode(self.node,*arg)

如果

推荐答案

我不认为通过Cython(问题是告诉Cython对任意数量的参数执行什么类型的转换)。我最好的建议是针对这种特定情况使用标准库ctypes库,并将其余的都包装在Cython中。

I don't think it's easily done though Cython (the problem is telling Cython what type conversions to do for an arbitrary number of arguments). The best I can suggest is to use the standard library ctypes library for this specific case and wrap the rest in Cython.

为了举例说明,我使用了一个非常简单的求和函数。 va_sum.h包含:

For the sake of an example, I've used a very simple sum function. va_sum.h contains:

typedef struct { double val; } node_bn;

node_bn* sum_va(node_bn* node,int len, ...);
/* on windows this must be:
__declspec(dllexport) node_bn* sum_va(node_bn* node,int len, ...);
*/

和va_sum.c包含:

and va_sum.c contains:

#include <stdarg.h>

#include "va_sum.h"

node_bn* sum_va(node_bn* node,int len, ...) {
    int i;
    va_list vl;
    va_start(vl,len);
    for (i=0; i<len; ++i) {
        node->val += va_arg(vl,double);
    }
    va_end(vl);
    return node;
}

我已经编写了它,因此它将所有内容添加到结构中的字段中来证明您可以毫不费力地传递指向结构的指针。

I've written it so it adds everything to a field in a structure just to demonstrate that you can pass pointers to structures without too much trouble.

Cython文件为:

The Cython file is:

# definition of a structure
cdef extern from "va_sum.h":   

    ctypedef struct node_bn:
        double val;

# obviously you'll want to wrap things in terms of Python accessible classes, but this atleast demonstrates how it works
def test_sum(*args):
    cdef node_bn input_node;
    cdef node_bn* output_node_p;
    input_node.val = 5.0 # create a node, and set an initial value

    from ctypes import CDLL, c_double,c_void_p
    import os.path
    # load the Cython library with ctypes to gain access to the "sum_va" function
    # Assuming you've linked it in when you build the Cython module
    full_path = os.path.realpath(__file__)
    this_file_library = CDLL(full_path)

    # I treat all my arguments as doubles - you may need to do
    # something more sophisticated, but the idea is the same:
    # convert them to the c-type the function is expecting
    args = [ c_double(arg) for arg in args ]
    sum_va = this_file_library.sum_va
    sum_va.restype = c_void_p # it returns a pointer

    # pass the pointers as a void pointer
    # my c compiler warns me if I used int instead of long
    # but which integer type you have to use is likely system dependent
    # and somewhere you have to be careful
    output_node_p_as_integer = sum_va(c_void_p(<long>&input_node),len(args),
                           *args)

    # unfortunately getting the output needs a two stage typecast - first to a long, then to a pointer
    output_node_p = <node_bn*>(<long>(output_node_p_as_integer))
    return output_node_p.val

您需要将va_sum.c和Cython文件一起编译(例如通过添加源= ['cython_file.pyx','va_sum.c'] 在setup.py中)

You need to compile your va_sum.c together with your Cython file (e.g. by adding sources = ['cython_file.pyx','va_sum.c'] in setup.py)

Ctypes可能比Cython慢​​一些(我认为每个调用都有合理的开销),并且将它们混合在一起很奇怪,但这至少应该让您在Cython中编写主包装,并使用ctypes来解决特定的限制

Ctypes is probably a bit slower than Cython (I think there's a reasonable overhead on each call), and it's odd to mix them, but this should at least let you write the main wrapper in Cython, and use ctypes to get round the specific limitation.

这篇关于相当于c的Cython定义#define myfunc(node x,...)SetNode(x.getattributeNode(),__ VA_ARGS__)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆