私は先に進み、それを包み、その例をJuliaに翻訳しました。 これはちょうど速かった&ダーティ(それは、より良いだろう、私はちょうどそれがC APIに一致させたジュリアのイテレータインターフェイスを使用しません) いくつかの点:C割り当てられたメモリが関与しているので、私はファイナライザを設定iteratorオブジェクトがスコープから外れてガベージコレクトされると、Cの割り当てられたメモリは解放されます。私はそれを明示的に解放できるようにしました(メモリを2回解放しようとするのを防ぐ)。 また、モジュールと各関数にはdoc文字列があります。私はそれが正しい結果だ願ってい
julia> @time example()
Sum of the primes below 10^10 = 2220820311119164929
5.836645 seconds (609 allocations: 16.324 KB)
:それは私がそれを実行したとき、私は以下の結果を得たC.
に構造体へのポインタを渡すためにRef
を使用しています!ここで
はちょうどIteratorインターフェイスの私の迅速なラッピングです:
"""
Wrapper for primesieves library
Copyright 2016 Scott Paul Jones
MIT Licensed
"""
module PrimeSieves
export PrimeSieveIterator, skipto, next, previous, free
const global psilib = "libprimesieve.dylib"
type PrimeSieveIterator
i::Csize_t
last_idx::Csize_t
primes::Ptr{UInt64}
primes_pimpl::Ptr{UInt64}
start::UInt64
stop::UInt64
stop_hint::UInt64
tiny_cache_size::UInt64
is_error::Cint
function PrimeSieveIterator()
piter = new(0,0,C_NULL,C_NULL,0,0,0,0,0)
ccall((:primesieve_init, psilib), Void, (Ref{PrimeSieveIterator},), piter)
finalizer(piter, free)
piter
end
end
""" Free all memory """
function free(piter::PrimeSieveIterator)
# Make sure it isn't freed twice
if piter.primes != C_NULL
ccall((:primesieve_free_iterator, psilib), Void, (Ref{PrimeSieveIterator},), piter)
piter.primes = C_NULL
piter.primes_pimpl = C_NULL
end
nothing
end
""" Set the primesieve iterator to start """
skipto(piter::PrimeSieveIterator, start::Integer, stop_hint::Integer) =
ccall((:primesieve_skipto, psilib), Void,
(Ref{PrimeSieveIterator}, UInt64, UInt64), piter, start, stop_hint)
""" Get the next prime """
function Base.next(piter::PrimeSieveIterator)
(piter.i-1) >= piter.last_idx &&
ccall((:primesieve_generate_next_primes, psilib), Void, (Ref{PrimeSieveIterator},), piter)
unsafe_load(piter.primes, piter.i += 1)
end
""" Get the previous prime """
function previous(piter::PrimeSieveIterator)
if piter.i == 0
ccall((:primesieve_generate_previous_primes, psilib),
Void, (Ref{PrimeSieveIterator},), piter)
else
piter.i -= 1
end
unsafe_load(piter.primes, piter.i + 1)
end
end
例のコードは次のようになります。
using PrimeSieves
function example()
pit = PrimeSieveIterator()
sum = UInt64(0)
# iterate over the primes below 10^10
while (prime = next(pit)) < UInt64(10000000000)
sum += prime
end
free(pit)
println("Sum of the primes below 10^10 = ", sum)
end
example()
あなたはドキュメントのこの部分をたどる試みたことがありますか? http://docs.julialang.org/en/release-0.4/manual/calling-c-and-fortran-code/ – Chisholm
これは私の最初のコールポートでした。しかし私は、例をhttp://primesieve.org/api/primesieve__iterator_8h.html#a4512ff6ce19e25042f07fe1337bb0dbeの定義に簡単に一致させることはできませんでした。私は、一般的なJuliaとは異なり、Cコードを呼び出すことは経験豊富なプログラマーにとってのみ重要な印象を与えました。 – u003f
JuliaからC APIへのラッパーを作成するのはかなり簡単です。経験豊富なプログラマーだけではありません(C言語を実際に使用することさえできません。ほとんどの場合、同等のジュリアタイプがあります)。 C APIをラップするのにどの部分が問題をもたらしましたか? –