Cython 等效于 c define #define myfunc(node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)
Cython equivalent of c define #define myfunc(node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)
Cython 等效于 c 定义
#define myfunc(Node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)
我有一个 c api SetNode,它的第一个参数是结构类型节点的节点和 N 个变量(N 是从 0-N 的变量数)
这里有一个解决此类问题的例子
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
#include<stdarg.h>
float sumN(int len,...)
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);
将 return 10.000000
sum(1.5,6.5);
将 return 8.00000
我需要一个 cython 替代品用于下面的 c 定义而不是上面的例子
因为我有一个 C-API ,它有一个 SetNode 函数,它接受可变数量的参数,我想把它包装在 cython 中并从 python
调用
#define myfunc(Node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)
这里的 Node 是在 cython 中定义的 class ,它持有一个 c 结构作为属性,getattributeNode() 是 Node class 的一个函数,需要传递 returns c 结构进入 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)
参数列表为空时工作正常
n = Node()
n.setNode() #This works
n.SetNode("top",1) # error takes exactly one argument given 3 in self._setNode(self.node,*arg)
如果有人能推荐与之等效的 cython,那就太好了。
这可能不是正确的答案,因为我不确定我是否完全理解这个问题。我会在评论中回复,但代码格式太差了。
在 Python 中,函数 sum
和 len
可用:
def my_len(*args):
return len(args)
def my_sum(*args):
return sum(args)
print "len =", my_len("hello", 123, "there")
print "sum =", my_sum(6.5, 1.5, 2.0)
输出:
len = 3
sum = 10.0
我不认为这很容易通过 Cython 完成(问题是告诉 Cython 对任意数量的参数执行什么类型转换)。我能建议的最好的办法是针对这种特定情况使用标准库 ctypes 库,并将其余部分包装在 Cython 中。
为了举例,我使用了一个非常简单的求和函数。 va_sum.h 包含:
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包含:
#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;
}
我编写它是为了将所有内容添加到结构中的字段,只是为了证明您可以轻松地将指针传递给结构。
Cython 文件是:
# 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 文件一起编译(例如 setup.py 中的 adding sources = ['cython_file.pyx','va_sum.c']
)
Ctypes 可能比 Cython 慢一点(我认为每次调用都有合理的开销),混合使用它们很奇怪,但这至少应该让你在 Cython 中编写主包装器,并使用 ctypes 来绕过特定限制。
Cython 等效于 c 定义
#define myfunc(Node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)
我有一个 c api SetNode,它的第一个参数是结构类型节点的节点和 N 个变量(N 是从 0-N 的变量数)
这里有一个解决此类问题的例子
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
#include<stdarg.h>
float sumN(int len,...)
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);
将 return 10.000000
sum(1.5,6.5);
将 return 8.00000
我需要一个 cython 替代品用于下面的 c 定义而不是上面的例子 因为我有一个 C-API ,它有一个 SetNode 函数,它接受可变数量的参数,我想把它包装在 cython 中并从 python
调用 #define myfunc(Node x,...) SetNode(x.getattributeNode(),__VA_ARGS__)
这里的 Node 是在 cython 中定义的 class ,它持有一个 c 结构作为属性,getattributeNode() 是 Node class 的一个函数,需要传递 returns c 结构进入 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)
参数列表为空时工作正常
n = Node()
n.setNode() #This works
n.SetNode("top",1) # error takes exactly one argument given 3 in self._setNode(self.node,*arg)
如果有人能推荐与之等效的 cython,那就太好了。
这可能不是正确的答案,因为我不确定我是否完全理解这个问题。我会在评论中回复,但代码格式太差了。
在 Python 中,函数 sum
和 len
可用:
def my_len(*args):
return len(args)
def my_sum(*args):
return sum(args)
print "len =", my_len("hello", 123, "there")
print "sum =", my_sum(6.5, 1.5, 2.0)
输出:
len = 3
sum = 10.0
我不认为这很容易通过 Cython 完成(问题是告诉 Cython 对任意数量的参数执行什么类型转换)。我能建议的最好的办法是针对这种特定情况使用标准库 ctypes 库,并将其余部分包装在 Cython 中。
为了举例,我使用了一个非常简单的求和函数。 va_sum.h 包含:
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包含:
#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;
}
我编写它是为了将所有内容添加到结构中的字段,只是为了证明您可以轻松地将指针传递给结构。
Cython 文件是:
# 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 文件一起编译(例如 setup.py 中的 adding sources = ['cython_file.pyx','va_sum.c']
)
Ctypes 可能比 Cython 慢一点(我认为每次调用都有合理的开销),混合使用它们很奇怪,但这至少应该让你在 Cython 中编写主包装器,并使用 ctypes 来绕过特定限制。