On Mon, Nov 30, 2015 at 5:23 AM, Felix <[email protected]> wrote:
> Hi,
>
> I can't seem to get a hang of how to call a C function that essentially
> needs a string containing the path to a file as input, but it is declared as
> a structure containing a const char. The setup is the following (SPICE
> library):
>
> I want to call the function:
>
> void furnsh_c ( ConstSpiceChar * file ) { ... }
>
> with the structure ConstSpiceChar being defined as:
>
> typedef const char ConstSpiceChar;
>
> I don't know how to call that from Julia. What I have tried and modified in
> many ways is the following:
>
> immutable ConstSpiceChar
> x::Ptr{UInt8}
> end
>
> kernel = ConstSpiceChar(pointer("../../../../cspice/kernels/sat317.bsp"))
This is undefined behavior, the string can be garbage collected when
you are still holding a pointer to it.
>
> ccall((:furnsh_c , spicelib), Void, (Ptr{ConstSpiceChar},) ,
> pointer(kernel))
pointer is not what you want and this is also undefined behavior even
if you replace pointer with the correct function that returns the
pointer to the object.
What you should actually do to fix the first problem depends on the
actual usecase but there's an example what you can do.
immutable JLConstSpiceChar
ptr::Ptr{UInt8}
str
function JLConstSpiceChar(_str)
str = Base.cconvert(Cstring, _str)
ptr = Base.unsafe_convert(Cstring, str)
# This is effectively doing what ccall does to make it GC safe to pass
# a string to a c function that expect a pointer.
# See doc for unsafe_convert and cconvert.
new(ptr, str)
end
end
kernel = ConstSpiceChar("../../../../cspice/kernels/sat317.bsp")
ccall((:furnsh_c , spicelib), Void, (Ref{ConstSpiceChar},) ,kernel)
>
> Which ends up in an error:
>
> LoadError: TypeError: anonymous: in ccall: first argument not a pointer or
> valid constant expression, expected Ptr{T}, got Tuple{Symbol,ASCIIString}
>
> I hope there is an easy solution to this. I am not very skilled in C.
>
> Thanks, Felix.
>
>