【发布时间】:2017-11-14 21:46:33
【问题描述】:
我是 cython 的新手,有一点 C 知识和一些 python 经验。目前我正在尝试了解扩展类型,但我无法理解以下示例中的指针值会发生什么(解释下方的代码)。
作为练习,我正在实现一个虚拟求解器。问题由两个数字“a”和“b”表示,解决方案由“s”表示,其中 s = a*b。
我定义了两个对应的C结构,problem和solution。问题结构有两个 int 成员,'a' 和 'b';解决方案结构有一个成员's'。有一个函数可以初始化问题结构,init_problem(problem *p,int a, int b)。此外,还有一个函数采用指向结构的指针并返回解决方案,solution solve(problem *p)。最后,另外两个函数打印值(void dump_problem(problem *p)和void dump_solution(solution *s))。所有这些都使用cdef 声明。
接下来,我使用了三种方法将 C 代码公开给 python:一个 def 函数 do_things(int a,int b) 包装了 C 函数,以及两个 cdef class,一个使用结构作为属性,另一个使用指向结构的指针作为属性(分别为Solver_s 和Solver_p),包括打印问题和解决方案的包装方法。 Solver_s 类按预期工作;但是,当使用 Solver_p 时,指针似乎没有被初始化,返回不正确的值(参见 test_pointers 和输出部分)。
我想我错过了关于指针及其范围的一个要点,但我无法理解发生了什么。非常感谢任何帮助。我在 OS X 10.11.6 (El Capitan) 中使用 python 3.5.3 和 cython 0.25.2
P.S:第一次问,所以如果我不清楚,我很乐意澄清!
pointers.pyx
from libc.stdio cimport printf
cdef struct problem:
int a
int b
cdef struct solution:
int s
cdef void init_problem(problem *p,int a, int b):
p.a = a
p.b = b
cdef solution solve(problem *p):
cdef solution s
s.s = p.a * p.b
return(s)
cdef void dump_problem(problem *p):
printf("Problem dump: a = %d,b = %d\n",p.a,p.b)
cdef void dump_solution(solution *s):
printf("Solution dump: s= %d\n",s.s)
def do_things(int a,int b):
cdef problem p
init_problem(&p,a,b)
cdef solution s = solve(&p)
dump_problem(&p)
dump_solution(&s)
cdef class Solver_s: #Structs as attributes of Solver
cdef problem p
cdef solution s
def __cinit__(self,int a,int b):
print("\tInside Solver_s __cinit__")
init_problem(&self.p,a,b)
dump_problem(&self.p)
self.s = solve(&self.p)
dump_solution(&self.s)
print("\tGetting out of Solver_s __cinit__")
def show_problem(self):
dump_problem(&self.p)
def show_solution(self):
dump_solution(&self.s)
cdef class Solver_p: #Pointers to structs as attributes
cdef problem *pptr
cdef solution *sptr
def __cinit__(self,int a, int b):
print("\tInside Solver_p __cinit__")
cdef problem p
self.pptr = &p
cdef solution s
self.sptr = &s
init_problem(self.pptr,a,b)
dump_problem(self.pptr) #It shows right values
self.sptr[0] = solve(self.pptr)
dump_solution(self.sptr) #It shows right values
print("\tGetting out of Solver_p __cinit__")
def show_problem(self):
dump_problem(self.pptr)
def show_solution(self):
dump_solution(self.sptr)
test_pointers.py
import pyximport; pyximport.install()
import pointers
print("\tSolving as a function")
pointers.do_things(2,3)
print("\tSolving as a Extended Type, structs as attributes")
sol_s = pointers.Solver_s(4,5)
print("\t###Problem definition unsing Solver_s methods###")
sol_s.show_problem()
print("\t###Solution definition using Solver_s methods###")
sol_s.show_solution()
print("\tSolving as a Extended Type, pointers to structs as attributes")
sol_p = pointers.Solver_p(6,7)
print("\t###Problem definition unsing Solver_p methods###")
print("\t###Gives weird values###")
sol_p.show_problem()
print("\t###Solution definition using Solver_p methods###")
print("\t###Gives weird values###")
sol_p.show_solution()
输出
Solving as a function
Problem dump: a = 2,b = 3
Solution dump: s= 6
Solving as a Extended Type, structs as attributes
Inside Solver_s __cinit__
Problem dump: a = 4,b = 5
Solution dump: s= 20
Getting out of Solver_s __cinit__
###Problem definition unsing Solver_s methods###
Problem dump: a = 4,b = 5
###Solution definition using Solver_s methods###
Solution dump: s= 20
Solving as a Extended Type, pointers to structs as attributes
Inside Solver_p __cinit__
Problem dump: a = 6,b = 7
Solution dump: s= 42
Getting out of Solver_p __cinit__
###Problem definition unsing Solver_p methods###
###Gives weird values###
Problem dump: a = 1,b = 0
###Solution definition using Solver_p methods###
###Gives weird values###
Solution dump: s= 185295816
【问题讨论】: