2016-10-19 1 views
9

Ok, ich ursprünglich schlecht vermasselte meine Formulierung dieser Frage (es ist mehr als ein Jahr jetzt, da ich C++ Code ernsthaft geschrieben und ich habe ziemlich begrenzte Erfahrung mit reinem C) zu erklären, so Lass es uns erneut versuchen.die richtige Art und Weise C void-Zeiger in Julia

Einig C-Code geschrieben ist zu erwarten, dass Sie so etwas wie die folgenden

void* p; 
create_new_thing(&p); //p is now a new thing 
do_stuff_to_thing(p); //something happened to p 

Meine Frage zu tun ist, wie das Objekt p in Julia zu erstellen. Im Moment glaube ich, die Antwort

p = Ref{Ptr{Void}}() 
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p) 
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p) 

Darüber zu sein, ich glaube, den gleichen Code aber mit p erklärte stattdessen als p = Array(Ptr{Void}, 1) auch funktioniert.

Ich finde jedoch die ganze Unterscheidung zwischen Ref und Ptr in Julia sehr verwirrend, vor allem, weil sie scheinen sich gegenseitig auf Wegen umgewandelt werden, die ich nicht im Auge behalten kann.

+0

Detail: mit 'void * p;', 'P' ist eine "neue Sache"(Objekt). 'Create_new_thing (&p);' 'die Funktion _assign_ ermöglicht P' Wert. Viel Glück mit Julia. – chux

+0

Verstanden, ich der Grund, nicht das Wort Objekt wurde ist, dass ich besorgt war sehr spezifisch über zu sein. Eine mit tun könnte, sagt ihnen, ein unveränderlicher numerischer Typ. –

+0

In C _object_ ist der _general_ Begriff für „Bereich der Datenspeicherung ..., dessen Inhalt kann Werte repräsentieren“ wie Zeichen, Zahlen, Gleitkomma, Zeiger, Arrays, Strukturen, Gewerkschaften, und Konstanten. Alles, auf das man mit Ausnahme von Funktionen zeigen kann. – chux

Antwort

9

Ihr Code sieht fast in Ordnung. Aber sei vorsichtig! Jede kleine Fehler, wie die, die Sie hier haben, können einen Segmentierungsfehler verursachen:

p = Ref{Ptr{Void}}() 
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p) 
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p) 
             # error here^

Der richtige Weg, es zu tun ist

p = Ref{Ptr{Void}}() 
ccall((:create_new_thing, :lib), Void, (Ptr{Ptr{Void}},), p) 
ccall((:do_stuff_to_thing, :lib), Void, (Ptr{Void},), p[]) 
              # fixed^

Der einfachste Weg, um zu verstehen, wo die Verwendung p und p[] ist an den entsprechenden C-Code denken. In C schreiben wir

void *p; 
create_new_thing(&p) 
do_stuff_to_thing(p) 

Julia Objekte haben keinen First-Class-Speicheradressen wie C-Objekte zu tun, so müssen wir p = Ref{Ptr{Void}}() in Julia verwenden, um eine Speicheradresse zu erhalten. Dieses Objekt verhält sich wie ein Verweis wie &p in C. Das heißt, um das Objekt selbst zu erhalten, in C, müssen wir p[] in Julia verwenden.

So entspricht in Julia ist

p = Ref{Ptr{Void}}()     # this p corresponds to &p in C 
ccall(:create_new_thing, ..., p)  # like &p 
ccall(:do_stuff_to_thing, ..., p[]) # like *(&p); that is, like p 
+1

Die erste 'ccall'-Signatur sollte wahrscheinlich auch' Ref {Ptr {Void}} 'anstelle von' Ptr {Ptr {Void}} 'lauten: http://docs.julialang.org/en/release-0.5/manual/calling-c-and-fortran-code/#passing-pointers-for-modifying-inputs –

+1

@SimonByrne Von meinem Verständnis sind sie in diesem Fall genau das gleiche, also habe ich den Code des OPs nur gespeichert –

+1

Ich denke, dass sie im Moment gleichwertig sind, aber das Handbuch empfiehlt "Ref" für veränderbare Zeiger. –

Verwandte Themen