# How to pass Ref of struct containing Cstring to Fortran

**URL:** <https://discourse.julialang.org/t/how-to-pass-ref-of-struct-containing-cstring-to-fortran/107878>\
**Category:** General Usage\
**Created:** [December 20, 2023, 8:57pm UTC](https://discourse.julialang.org/t/how-to-pass-ref-of-struct-containing-cstring-to-fortran/107878 "2023-12-20T20:57:08Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![danielmatz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielmatz/32/2285_2.png) [@danielmatz](https://discourse.julialang.org/u/danielmatz)\
**Post date:** [December 20, 2023, 8:57pm UTC](https://discourse.julialang.org/t/how-to-pass-ref-of-struct-containing-cstring-to-fortran/107878/1 "2023-12-20T20:57:08Z")

</div>

I have a struct that contains a `Cstring`. I saw this older post about how to pass such a struct to C:

> [@Pass structure containing String to C code](https://discourse.julialang.org/t/pass-structure-containing-string-to-c-code/1667):
>
> pass structure containing string to C code type simcase a::Int32 b::Int32 c::Cstring end n = 2 m = 3 x = randn(n,m) s = simcase(3,4,Cstring("hello")) ccall((:printArray, "./test\_array.so"), Void, ( Ptr{Float64}, Int32, Int32, simcase), x, Int32(n), Int32(m), s) produces: julia\> ERROR: LoadError: MethodError: Cannot `convert` an object of type String to an object of type Cstring This may have arisen from a call to the constructor Cstring(...), since type constructors fall back to …

I need to pass such a struct to Fortran (the Fortran code converts the C-style string to a Fortran string), so that means I need to pass a `Ref` of my struct. I’m struggling to define the appropriate `Base.cconvert` and `Base.unsafe_convert` methods.

My current attempt is essentially trying to put a `Ref` around the answer from the post linked above. Simplifying things a bit:

```julia
struct Foo
    s::String
end

struct FooC
    s::CString
end

# Base.cconvert(::Type{Cstring}, s::String) just returns s, so we can just pass through the struct, wrapping it with a Ref
Base.cconvert(::Type{Ref{FooC}}, foo::Foo) = Ref(foo)

function Base.unsafe_convert(::Type{Ref{FooC}}, foo)
    Base.unsafe_convert(Ptr{FooC}, Ref(FooC(Base.unsafe_convert(Cstring, foo[].s))))
end

foo = Foo("hi")
@ccall my_lib.my_fun(foo::Ref{FooC})::Cvoid

```

My code yields `signal (10.1): Bus error: 10`. I gather that means that the pointer I’m passing to Fortran is referencing memory that the current process isn’t allowed to access.

Any help would be greatly appreciated! Thanks!

---

<div class="post-metadata">

**Author:** ![danielmatz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielmatz/32/2285_2.png) [@danielmatz](https://discourse.julialang.org/u/danielmatz)\
**Post date:** [January 9, 2024, 6:02pm UTC](https://discourse.julialang.org/t/how-to-pass-ref-of-struct-containing-cstring-to-fortran/107878/2 "2024-01-09T18:02:58Z")

</div>

I’m embarrassed to report that I had a mismatch in my struct definitions between Fortran and Julia, which was the cause of my `signal (10.1)`.

After fixing that, I made a new attempt at defining the `Base.cconvert` and `Base.unsafe_convert` methods. I’m still confused about how to properly handle `Ref`. Unwrapping to apply `Base.unsafe_convert` and then re-wrapping with `Ref` doesn’t seem to work.

I decided to use the fallback implementation of `Base.unsafe_convert` for dealing with `Ref`. I was able to get it to work by doing the following:

```julia
struct Foo
    s::String
end

struct FooC
    s::CString
end

function Base.cconvert(::Type{FooC}, foo::Foo)
    FooC(Base.unsafe_convert(Cstring, Base.cconvert(Cstring, foo.s)))
end

Base.convert(T::Type{FooC}, foo::Foo) = Base.cconvert(T, foo)

foo = Foo("hi")
@ccall my_lib.my_fun(foo::Ref{FooC})::Cvoid

```

I’m not sure if it is OK that I called `Base.unsafe_convert` for the `String` field within the `Base.cconvert` call for the containing struct.

---

<div class="post-metadata">

**Author:** ![mkitti](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mkitti/32/12459_2.png) [@mkitti](https://discourse.julialang.org/u/mkitti)\
**Post date:** [January 9, 2024, 7:24pm UTC](https://discourse.julialang.org/t/how-to-pass-ref-of-struct-containing-cstring-to-fortran/107878/3 "2024-01-09T19:24:42Z")

</div>

I think you should probably overload `Base.unsafe_convert` rather than `Base.cconvert` or `Base.convert` then.

```julia
julia> struct Foo
           s::String
       end

julia> struct FooC
           s::Cstring
       end

julia> Base.cconvert(::Type{FooC}, foo::Foo) = foo

julia> Base.unsafe_convert(::Type{FooC}, foo::Foo) = FooC(Base.unsafe_convert(Cstring, foo.s))

julia> my_c_function(fooc::FooC) = println(Base.unsafe_string(fooc.s))
my_c_function (generic function with 1 method)

julia> f_ptr = @cfunction(my_c_function, Nothing, (FooC,))
Ptr{Nothing} @0x00000235cfc63fe0

julia> fooey = Foo("Hello World")
Foo("Hello World")

julia> @ccall $f_ptr(fooey::FooC)::Nothing
Hello World

```

Here’s some highlighting of the relevant documentation.

```julia
help?> @ccall
  ...

  Each argvalue to @ccall is converted to the corresponding argtype, by automatic insertion of calls to
  unsafe_convert(argtype, cconvert(argtype, argvalue)). (See also the documentation for unsafe_convert and cconvert
  for further details.) In most cases, this simply results in a call to convert(argtype, argvalue).

help?> Base.unsafe_convert
  unsafe_convert(T, x)

    In cases where convert would need to take a Julia object and turn it into a Ptr, this function should be used to
  define and perform that conversion.

  Be careful to ensure that a Julia reference to x exists as long as the result of this function will be used.
  
help?> Base.cconvert
  cconvert(T,x)

    In cases where x cannot be safely converted to T, unlike convert, cconvert may return an object of a type different
  from T, which however is suitable for unsafe_convert to handle. The result of this function should be kept valid
  (for the GC) until the result of unsafe_convert is not needed anymore. This can be used to allocate memory that will
  be accessed by the ccall. If multiple objects need to be allocated, a tuple of the objects can be used as return
  value.

  Neither convert nor cconvert should take a Julia object and turn it into a Ptr.

```

---

<div class="post-metadata">

**Author:** ![danielmatz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielmatz/32/2285_2.png) [@danielmatz](https://discourse.julialang.org/u/danielmatz)\
**Post date:** [January 9, 2024, 8:04pm UTC](https://discourse.julialang.org/t/how-to-pass-ref-of-struct-containing-cstring-to-fortran/107878/4 "2024-01-09T20:04:05Z")

</div>

Your example isn’t passing a `Ref{FooC}`. What you have indeed makes sense for the non-`Ref` case. But once we have a `Ref`, it seems like I’d need to unwrap it in order to apply `Base.unsafe_convert` to the field.
