2015-03-07 1 views
-1

Une idée pourquoi cette fonction ne modifie pas le paramètre 'eta' mais renvoie la valeur attendue?Julia ne modifie pas l'argument après ccall

function str2et!(date::String, eta::SpiceDouble) 
    ptr = convert(Ptr{ConstSpiceChar}, date) 
    et = Array(SpiceDouble,1) 
    ccall((:str2et_c,"/home/don/.julia/v0.3/cspice.so"),Void,(Ptr{ConstSpiceChar},Ptr{SpiceDouble}), 
       ptr, 
       et) 
    eta = et[1] 
end 
+1

Juste pour clarifier: [* Les fonctions qui modifient leurs entrées ont des noms qui se terminent dans '!' *] (http://docs.julialang.org/fr/release-0.3/manual/variables/#stylistic-conventions), mais ceci est juste une convention de nommage et n'a aucun impact sur le comportement de la fonction . Ici, nommer votre fonction 'str2et!', Avec un point d'exclamation à la fin, ne le rend pas mutable. – Jubobs

+0

... Je voulais dire * mutant *, pas * mutable *. – Jubobs

+0

La compilation suivante, mais ne fonctionne pas. La valeur initiale de zéro est remplacée par le 2, mais le ccall ne modifie pas le champ v. 'Type Mutable valeur fin convert (type {:: Mutable}, v :: Float64) = v fonction returnViaDoublePtr() angle = Mutable (0,0) angle.value = 2 ccall ((: raxisa_c, libNasaSpice), vide, (Ptr {Float64},), pointer_from_objref (angle)) return angle.value end' – user2154643

Répondre

3

Votre problème est semblable au suivant

function f(x) 
    x=1 
end 

La fonction ne modifier l'argument, mais remplace il.

y=2 
f(y) 
y  # Still 2 -- no side effect 
f(2) # Equivalent to f(y) 

Si vous souhaitez que la valeur soit modifiée, vous pouvez définir votre propre type (mutable).

type Result 
    value 
end 
function g(x::Result) 
    x.value = 1 
end 
y=Result(2) 
y.value # This is 2 
g(y) 
y.value # This is now 1 

Dans cet exemple, bien sûr, il serait plus clair de renvoyer une valeur.

+0

OK Je comprends que seuls les types déclarés sont mutables. Cependant, j'essaie de m'interfacer avec certaines routines en langage C qui renvoient des valeurs en utilisant des arguments double *. si vous remplacez le x.value = 1 dans votre fonction g() avec ccall ((: gc, "somelib", Void, (Ptr {Float64},), la valeur (& x.value)) n'est pas modifiée. pass & x non plus pouvez-vous prendre le pointeur (x) – user2154643

+0

Vous pouvez obtenir un pointeur en utilisant pointer_from_obj_ref() – user2154643

0

La création d'un type mutable n'est pas la solution; mais faire un tableau à une élément fonctionne, mais ne semble pas très efficace (code_native la fonction suivante donne un écrans couple d'assembleur)

void raxisa_c(double* x) { 
    *x = 3; 
} 

function returnViaDoublePtr() 
    angle = Array{Float64}(1) 
    ccall((:raxisa_c,libNasaSpice),Void, 
     (Ptr{Float64},), 
     angle) 
     return angle[1] 
end