私はC++ライブラリを乱数ジェネレータを生成する親と均等に分布する乱数を生成するために使用する子を使ってcythonで動作させようとしています。コードが正しくコンパイルもののCython - stdlibを使って<random>
[rnd.pyx]
cdef extern from "<random>" namespace "std":
cdef cppclass mt19937:
mt19937() except +
mt19937(unsigned int) except +
cdef cppclass uniform_real_distribution[T]:
uniform_real_distribution()
uniform_real_distribution(double, double)
T operator()(mt19937)
cdef class Child:
cdef mt19937 *rng
cdef uniform_real_distribution[double] uniform
def __cinit__(Child self):
cdef unsigned int seed = 123154654
self.rng = NULL
self.uniform = uniform_real_distribution[double](0.,1.)
cdef set_rng(Child self, mt19937 rng):
self.rng = &rng
def gen_uniform(self):
return self.uniform(self.rng[0])
cdef class Parent:
cdef mt19937 rng
cdef public list children
def __cinit__(Parent self):
cdef unsigned int seed = 123154654
self.rng = mt19937(seed)
self.children = []
cpdef make_child(Parent self):
child = Child()
child.set_rng(self.rng)
self.children.append(child)
[rnd.pyxbuild]
import os
from distutils.extension import Extension
dirname = os.path.dirname(__file__)
def make_ext(modname, pyxfilename):
return Extension(
name=modname,
sources=[pyxfilename],
extra_compile_args=["-std=c++11"],
language="c++",
include_dirs=[dirname]
)
[test.py]
import pyximport
pyximport.install()
from rnd import Child, Parent
p = Parent()
for i in range(300):
p.make_child()
for child in p.children:
a = child.gen_uniform()
print(a)
しかし、gen_uniform
関数の出力は、私が期待するものは本当にありません:test.py
コードは最初0.941197317223、永遠に続い0.743410046664生成します。私はChild.gen_uniform
を変更し、それを再現するために管理していないのに
また、私はかつて大きな乱数(あまり)を取得するために管理している私からrng
ポインタを渡し、より複雑なコードでは最終的に1.0
私は普通の数字、ゼロ、1より大きい数値、次にセグメント化の誤りを得る。
誰かが問題の原因を教えてもらえますか?
ありがとうございました! (これはあまりにも明白ですが、私のC++は本当に錆びていると思います...) – Silmathoron
本当に、生涯で間違っているものを少し詳しく説明できますか?この例ではうまくいきますが、私の完全なコードでは、私は子供たちに孫を抱き、「親の子供のために」子供として繰り返します:子供の孫のために。子供たち: ''ループの最後にセグメンテーションを与えます'' parent.children [i] .children [j] ''を使って直接アクセスすると、segfaultが返されません... – Silmathoron
どこで起こっているのかすぐには推測できません。最も良い説明は: 'Parent'と' Child'はPythonクラスであり、その寿命はPython refcountingメカニズムによって制御されます(安全に使用する必要があります)。危険なのは 'Child'(おそらく' grandchild')が親の一部である乱数ジェネレータへのポインタを持っているのですが、これは親を生かしていないCポインタ(Pythonのリファレンスではない)ですからです。したがって、あなたがもはや 'parent'へのPythonリファレンスを保持しなくても、' Child'を保持している場合、 'Child'は無効なポインタを持つ可能性があります。 – DavidW