Package compiler and module global variable

module JModel
mutable struct JStruct
    path::String
   # other fields
end
jstruct = JStruct("")
Base.@ccallable function init_model(conf_path::Cstring)::Cint
    global jstruct
    jstruct = JStruct(unsafe_string(conf_path))
    return 0
end
Base.@ccallable function proc(evt::Ptr{Culong} )::Cint
    println("jstruct: ", jstruct.path)
    println("evt: $(unsafe_load(evt,1))")
    return 0
end
 
end # module JModel

Say I have to init a Julia struct from C passed in string and do a frequent proc call from C. Does using something like this global variable have a performance cost ? What’ s the Idiom way of doing something like this?

One important point to avoid issues is to either make the global const or add a type binding to it.

Here we use a const jstruct and we just mutate the field since your struct is mutable. The const just means we cannot assign a new value to jstruct. An important consequence for this for the compiler is that we know that the type of jstruct will not change. We can assume it will be of type JStruct.

const jstruct = JStruct("")
Base.@ccallable function init_model(conf_path::Cstring)::Cint
    global jstruct
    jstruct.path = unsafe_string(conf_path)
    return 0
end

Another way to do this is to add a type binding.

jstruct::JStruct = JStruct("")
Base.@ccallable function init_model(conf_path::Cstring)::Cint
    global jstruct
    jstruct = JStruct(unsafe_string(conf_path))
    return 0
end

You could use a Ref.

const jstruct_ref = Ref(JStruct(""))
Base.@ccallable function init_model(conf_path::Cstring)::Cint
    global jstruct
    jstruct[] = JStruct(unsafe_string(conf_path))
    return 0
end
Base.@ccallable function proc(evt::Ptr{Culong} )::Cint
    println("jstruct: ", jstruct[].path)
    println("evt: $(unsafe_load(evt,1))")
    return 0
end
1 Like