Ich ging weiter und wickelte es, und übersetzte dieses Beispiel zu Julia. Dies war nur schnell & schmutzig (es verwendet nicht die Julia Iterator-Schnittstelle, die wäre besser, ich habe es nur die C-API übereinstimmen) Ein paar Punkte: Weil es C zugeordneten Speicher beteiligt ist, richtete ich einen Finalizer Wenn das Iterator-Objekt den Gültigkeitsbereich verlässt und Garbage Collections erfasst, wird der C-Speicher weiterhin freigegeben. Ich habe es auch so gemacht, dass es explizit freigegeben werden kann (und davor geschützt ist, den Speicher zweimal zu befreien). Außerdem haben das Modul und jede Funktion einen Doc-String (den ich auch für den Typ angelegt haben sollte). Es verwendet Ref
einen Zeiger auf die Struktur C. passieren
Als ich es lief, habe ich folgendes Ergebnis:
julia> @time example()
Sum of the primes below 10^10 = 2220820311119164929
5.836645 seconds (609 allocations: 16.324 KB)
Ich hoffe, das ist das richtige Ergebnis!
Hier ist meine schnelle Verpackung von nur Iterator-Schnittstelle:
"""
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
Der Beispielcode wäre:
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()
Haben Sie versucht, diesen Teil der Dokumentation folgen? http://docs.julaulang.org/en/release-0.4/manual/calling-c-and-fortran-code/ – Chisholm
Das war meine erste Anlaufstelle. Aber ich konnte die Beispiele nicht so einfach an die Definition anpassen: http://primesieve.org/api/primesieve__iterator_8h.html#a4512ff6ce19e25042f07fe1337bb0dbe Ich hatte den Eindruck, dass - im Gegensatz zu Julia im Allgemeinen - der Aufruf von C-Code etwas für erfahrene Programmierer war. – u003f
Die Erstellung eines Wrappers für eine C-API von Julia ist ziemlich einfach, und es ist nicht nur für "erfahrene" Programmierer (Sie wissen nicht einmal wirklich C, um es zu tun, in den meisten Fällen müssen Sie nur verstehen, was die äquivalenten Julia Typen sind). Welche Teile des Umbruchs der C-API gab Ihnen Probleme? –