私はcythonの初心者です。現在、拡張型について学習しようとしていますが、次の例(説明の下にあるコード)でポインタの値がどうなるか理解できません。拡張型の属性としてのポインタcython
練習として、私はダミーソルバーを実装しています。問題は2つの数字「a」と「b」で表され、解は「s」(s = a * b)によって表されます。
私は2つの対応するCの構造、problem
とsolution
を定義しました。問題の構造体には、2つのintメンバー 'a'と 'b'があります。解構造には1つのメンバー 'があります。問題の構造体を初期化する関数は、init_problem(problem *p,int a, int b)
です。また、構造体へのポインタをとり、解を返す関数が1つあります(solution solve(problem *p)
)。最後に、他の2つの関数が値(void dump_problem(problem *p)
とvoid dump_solution(solution *s)
)を出力します。これらのすべてはcdef
宣言を使用しています。属性およびその他の属性として構造体へのポインタを用いたもの(Solver_s
とSolver_p
として構造体を使用して、C関数をラップdef
機能do_things(int a,int b)
、二つcdef class
、いずれか
次に私は、PythonにCコードを公開する3つの方法を使用しましたそれぞれ問題と解決策を印刷するためのラッピング方法を含む)。 Solver_sクラスは期待通りに動作します。ただし、Solver_pを使用すると、ポインタが初期化されていないように見え、不正な値が返されます(test_pointersと出力セクションを参照)。
私はポインタとその範囲についての細かい点を逃し推測するが、私は何が起こっているか理解できません。これを得るための助けがあれば幸いです。私はOS X 10.11.6(エルキャピタン)でpython 3.5.3とcython 0.25.2を使用しています
P .:最初に尋ねているので、明確ではない場合は明確にしておきます!
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