我是一名C語言和一些python經驗的知識的一位新手。目前我正在嘗試瞭解擴展類型,但我無法理解以下示例中指針值發生了什麼(代碼位於解釋下方)。指針作爲擴展類型的屬性cython
作爲練習,我正在實施虛擬解算器。問題由兩個數字'a'和'b'表示,解決方案由's'表示,其中s = a * b。
我定義了兩個相應的C結構,problem
和solution
。問題結構有兩個int成員,'a'和'b';解決方案結構有一個成員'。有一個函數可以初始化問題結構,init_problem(problem *p,int a, int b)
。此外,還有一個函數可以指向結構並返回一個解決方案,solution solve(problem *p)
。最後,另外兩個函數打印值(void dump_problem(problem *p)
和void dump_solution(solution *s)
)。所有這些使用cdef
聲明。
接着我用三種方式來暴露所述C代碼來蟒:一個def
功能do_things(int a,int b)
它包裝的C函數,以及兩個cdef class
,一個使用結構作爲屬性,並使用指針結構作爲屬性(Solver_s
和Solver_p
另一個,分別),包括打印方法來打印問題和解決方案。 Solver_s類按預期工作;然而,當使用Solver_p時,指針似乎不會被初始化,返回不正確的值(參見test_pointers和output部分)。
我想我錯過了一個關於指針和它們的範圍的細節,但我不明白髮生了什麼。任何幫助獲得這一點,不勝感激。我在OS X 10.11.6(El Capitan)中使用python 3.5.3和cython 0.25.2
P.S:第一次在SO中詢問,所以如果我不清楚,我會很樂意澄清!
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