Issue with Julia ccall interface and symbols - julia

I'm attemping to use Julia's ccall function to interface with a C library. All the types and pointers are correct, and the below function call successfully returns the correct answer (variable defintion and setup not shown here for brevity).
ccall((:vDSP_convD, libacc), Void,
(Ptr{T}, Int64, Ptr{T}, Int64, Ptr{T}, Int64, UInt64, UInt64),
x_padded, 1, pointer(K, Ksize), -1, result, 1, Rsize, Ksize)
However, if I wish to generate the function name as a symbol, and then use it as an argument to ccall, it fails.
fname = symbol(string("vDSP_conv", "D"))
ccall((fname , libacc), Void,
(Ptr{T}, Int64, Ptr{T}, Int64, Ptr{T}, Int64, UInt64, UInt64),
x_padded, 1, pointer(K, Ksize), -1, result, 1, Rsize, Ksize)
The error is:
ERROR: LoadError: TypeError: conv: in ccall: first argument not a
pointer or valid constant expression, expected Ptr{T},
got Tuple{Symbol,ASCIIString}
If I print the type of each of these two naming versions, I get
julia> println(typeof(:vDSP_convD))
Symbol
julia> println(typeof(fname))
Symbol
Is there a way to get this to work? I'm guessing that I will have to wrap this in a macro or #eval to get this work, but I am curious as to why the above functionality doesn't work as shown?
Any help will be most appreciated!
EDIT
I ended up wrapping this in an #eval block to get it to work; however, I'm still curious as to the backend logic as to why the above syntax doesn't work (why it interprets a symbol as a pointer sometimes, and then not other times)

ccall is not really a function – it's a syntactic form that is translated to a C function call using the C ABI. To emit a call to a C function, you need to be able to statically resolve the address of the function – that's where this requirement comes from. Note that in both C and Julia you can also call a function using a variable function pointer. In Julia, there are a few ways to get such a pointer, typically by using dlopen and dlsym. What ccall won't do is resolve a function by non-constant name: this is impossible in C (without a building yourself a lookup table); in Julia you can do this, as you've figured out, by using eval – but there is compiler overhead to doing this. That is why ccall won't do this automatically: you don't want to run the risk of accidentally introducing compiler overhead in a loop, for example.

Related

ERROR: setfield! immutable struct cannot be changed in Julia

I am updating some old code and I am now getting errors: ERROR: setfield! immutable struct cannot be changed in Julia when I try to change the values of an immutable struct. Is there a common workaround for how I can edit/mutate those values (this may be a rather silly question given that the type is explicitly immutable so it's not a good idea generally to try and change it).
As far as I remember immutables can not be safely manipulated even if you get a memory pointer to them and try to use ccal.
However, as an imperfect workaround you can consider using Setfield package as in the example below.
using Setfield
struct S
a::Int
b::String
end
Using:
julia> s = S(2, "hello")
S(2, "hello")
julia> s = #set s.a = 5
S(5, "hello")
Note that in many scenarios this might be faster than actually changing type of S to mutable.

Why is a Julia function name (without arguments) silently ignored?

I have a script that defines a function, and later intended to call the function but forgot to add the parentheses, like this:
function myfunc()
println("inside myfunc")
end
myfunc # This line is silently ignored. The function isn't invoked and there's no error message.
After a while I did figure out that I was missing the parentheses, but since Julia didn't give me an error, I'm wondering what that line is actually doing? I'm assuming that it must be doing something with the myfunc statement, but I don't know Julia well enough to understand what is happening.
I tried --depwarn=yes but don't see a julia command line switch to increase the warning level or verbosity. Please let me know if one exists.
For background context, the reason this came up is that I'm trying to translate a Bash script to Julia, and there are numerous locations where an argument-less function is defined and then invoked, and in Bash you don't need parentheses after the function name to invoke it.
The script is being run from command line (julia stub.jl) and I'm using Julia 1.0.3 on macOS.
It doesn't silently ignore the function. Calling myfunc in an interactive session will show you what happens: the call returns the function object to the console, and thus call's the show method for Function, showing how many methods are currently defined for that function in your workspace.
julia> function myfunc()
println("inside myfunc")
end
myfunc (generic function with 1 method)
julia> myfunc
myfunc (generic function with 1 method)
Since you're calling this in a script, show is never called, and thus you don't see any result. But it doesn't error, because the syntax is valid.
Thanks to DNF for the helpful comment on it being in a script.
It does nothing.
As in c, an expression has a value: in c the expression _ a=1+1; _ has the value _ 2 _ In c, this just fell out of the parser: they wanted to be able to evaluate expressions like _ a==b _
In Julia, it's the result of designing a language where the code you write is handled as a data object of the language. In Julia, the expression "a=1+1" has the value "a=1+1".
In c, the fact that
a=1+1;
is an acceptable line of code means that, accidentally,
a;
is also an acceptable line of code. The same is true in Julia: the compiler expects to see a data value there: any data value you put may be acceptable: even for example the data value that represents the calculated value returned by a function:
myfunc()
or the value that represents the function object itself:
myfunc
As in c, the fact that data values are everywhere in your code just indicates that the syntax allows data values everywhere in your code and that the compiler does nothing with data values that are everywhere in your code.

Parametric functors in Julia

Starting 0.6 it is possible to create parametric methods in Julia using where syntax. According to the release notes of 0.6 version, where syntax
can be used anywhere a type is accepted
Now consider the following contrived example:
function (rng::R)() where {R <: Range}
return first(rng)
end
which, when I attempt to compile it, gives the following error:
ERROR: function type in method definition is not a type
So my question is what is the proper way to create parametric functors in Julia 0.6+?
Ohkay, I get what you are trying to do basically. To understand functors here is a short example code.
julia> struct Student
name::String
end
julia> function (::Student)()
println("Callable of Student Type!")
end
julia> object = Student("JuliaLang")
Student("JuliaLang")
julia> object()
Callable of Student Type!
but when I try to create the parametric functors, it throws out the error similar to yours!
julia> function (::T)() where {T <: Student}
println("Callable of Student Type!")
end
ERROR: function type in method definition is not a type
This problem is actually still OPEN as a issue as #gnimuc rightly pointed out.
You mix up two things
parametric methods e.q. julia> same_type(x::T, y::T) where {T} = true
function-like objects e.g. julia> function (p::Polynomial)(x) ... end
To my knowledge there is no "parametric function-like objects"
However, the following code should be the same of what you intend.
Julia> function (rng::Range)()
return first(rng)
end
cannot add methods to an abstract type
The current docu does not mention any limitation of function-like objects to concrete type, but unfortunately Julia doesn't accept it anyway.

Polymorphic functions and subtypes in julia

I am learning Julia and for that purpose I am building a simulation of a scheduler for some non specified task. For this I want to create an abstract type, which represents the idea of state. A task could be in any state Accepted, Unfulfilled, Running, Finished:
abstract RequestState
Then I add some concrete states, which have RequestState as superstate:
immutable StateAccepted <: RequestState
name :: String
end
And because each state is immutable anyway and it doesn't have an interesting structure, all instances are the same, so I instantiate an instance of the above type to use:
const Accepted = StateAccepted("Accepted")
I generate this with a macro, perhaps it is relevant.
Now comes the problem. I want to write a function, which checks valid transitions. I only have a skeleton at this point:
function checkTransition{T <: RequestState, Q <: RequestState}(t :: T, q :: Q) :: Bool
return true
end
I assumed I should read the expression:
T <: RequestState
As something like forall T which is a subtype of RequestState, but I think this is wrong.
I would expect that this code compiles. The problem is that I don't understand the error and also can't find anything in the documentation. Note that this could be, because I am unfamiliar with the language. The relevant error is:
Error During Test
Expression evaluated to non-Boolean
Expression: checkTransition(Accepted,Running)
Value: ResourceScheduler.StateRunning("Running")
ERROR: LoadError: There was an error during testing
in record(::Base.Test.FallbackTestSet, ::Base.Test.Error) at ./test.jl:397
in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281
in include_from_node1(::String) at ./loading.jl:488
in process_options(::Base.JLOptions) at ./client.jl:262
in _start() at ./client.jl:318
while loading /home/eklerks/.julia/v0.5/ResourceScheduler/test/runtests.jl
How would I make a generic function accepting only arguments of subtypes of RequestState?
EDIT:
As requested the offending test:
#test checkTransition(Accepted, Running)
But this didn't work out, because I forgot to update and install my package after I changed it. Before that change it read:
function checkTransition{T <: RequestState, Q <: RequestState}(t :: T, q :: Q) :: Q
return q
end
Which was the source of the error. Type Q is indeed not a Boolean. I was experimenting with the type system at that moment.
While your code should work, typically one writes
checkTransition(t::RequestState, q::RequestState) = true
instead of using the unnecessary T <: RequestState parameterization. Note that f{T <: X}(::T) should not be read as "for all T subtype of X", but rather "there exists T subtype of X", as this is an existential type and not a universal type.
The error you're getting is due to checkTransition(Accepted,Running) returning a non-boolean, which must be due to a mistake unrelated to the code that you've posted.

julia introspection - get name of variable passed to function

In Julia, is there any way to get the name of a passed to a function?
x = 10
function myfunc(a)
# do something here
end
assert(myfunc(x) == "x")
Do I need to use macros or is there a native method that provides introspection?
You can grab the variable name with a macro:
julia> macro mymacro(arg)
string(arg)
end
julia> #mymacro(x)
"x"
julia> #assert(#mymacro(x) == "x")
but as others have said, I'm not sure why you'd need that.
Macros operate on the AST (code tree) during compile time, and the x is passed into the macro as the Symbol :x. You can turn a Symbol into a string and vice versa. Macros replace code with code, so the #mymacro(x) is simply pulled out and replaced with string(:x).
Ok, contradicting myself: technically this is possible in a very hacky way, under one (fairly limiting) condition: the function name must have only one method signature. The idea is very similar the answers to such questions for Python. Before the demo, I must emphasize that these are internal compiler details and are subject to change. Briefly:
julia> function foo(x)
bt = backtrace()
fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
Base.arg_decl_parts(fobj.env.defs)[2][1][1]
end
foo (generic function with 1 method)
julia> foo(1)
"x"
Let me re-emphasize that this is a bad idea, and should not be used for anything! (well, except for backtrace display). This is basically "stupid compiler tricks", but I'm showing it because it can be kind of educational to play with these objects, and the explanation does lead to a more useful answer to the clarifying comment by #ejang.
Explanation:
bt = backtrace() generates a ... backtrace ... from the current position. bt is an array of pointers, where each pointer is the address of a frame in the current call stack.
Profile.lookup(bt[3]) returns a LineInfo object with the function name (and several other details about each frame). Note that bt[1] and bt[2] are in the backtrace-generation function itself, so we need to go further up the stack to get the caller.
Profile.lookup(...).func returns the function name (the symbol :foo)
eval(current_module(), Profile.lookup(...)) returns the function object associated with the name :foo in the current_module(). If we modify the definition of function foo to return fobj, then note the equivalence to the foo object in the REPL:
julia> function foo(x)
bt = backtrace()
fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
end
foo (generic function with 1 method)
julia> foo(1) == foo
true
fobj.env.defs returns the first Method entry from the MethodTable for foo/fobj
Base.decl_arg_parts is a helper function (defined in methodshow.jl) that extracts argument information from a given Method.
the rest of the indexing drills down to the name of the argument.
Regarding the restriction that the function have only one method signature, the reason is that multiple signatures will all be listed (see defs.next) in the MethodTable. As far as I know there is no currently exposed interface to get the specific method associated with a given frame address. (as an exercise for the advanced reader: one way to do this would be to modify the address lookup functionality in jl_getFunctionInfo to also return the mangled function name, which could then be re-associated with the specific method invocation; however, I don't think we currently store a reverse mapping from mangled name -> Method).
Note also that (1) backtraces are slow (2) there is no notion of "function-local" eval in Julia, so even if one has the variable name, I believe it would be impossible to actually access the variable (and the compiler may completely elide local variables, unused or otherwise, put them in a register, etc.)
As for the IDE-style introspection use mentioned in the comments: foo.env.defs as shown above is one place to start for "object introspection". From the debugging side, Gallium.jl can inspect DWARF local variable info in a given frame. Finally, JuliaParser.jl is a pure-Julia implementation of the Julia parser that is actively used in several IDEs to introspect code blocks at a high level.
Another method is to use the function's vinfo. Here is an example:
function test(argx::Int64)
vinfo = code_lowered(test,(Int64,))
string(vinfo[1].args[1][1])
end
test (generic function with 1 method)
julia> test(10)
"argx"
The above depends on knowing the signature of the function, but this is a non-issue if it is coded within the function itself (otherwise some macro magic could be needed).

Resources