# Calling a C function from within a Julia program

**URL:** <https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643>\
**Category:** General Usage\
**Tags:** question, ccall, c\
**Created:** [June 27, 2021, 11:43am UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643 "2021-06-27T11:43:51Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 27, 2021, 11:43am UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/1 "2021-06-27T11:43:51Z")

</div>

Hi! I’m using Julia 1.6.1 on a MacBook Pro and trying to use the MISR-Toolkit library of C functions within Julia programs. This library is maintained by NASA/JPL and available from GitHub at

> **[GitHub - nasa/MISR-Toolkit: an API facilitating the access of MISR standard...](https://github.com/nasa/MISR-Toolkit)**
>
> an API facilitating the access of MISR standard product files - GitHub - nasa/MISR-Toolkit: an API facilitating the access of MISR standard product files

I was able to access function `MtkVersion` from this library (which requires no argument and retrieves the version number of the Toolkit), so the library is correctly installed:

```julia
julia> mtklib = "/Applications/Mtk-1.5.0/lib/libMisrToolkit.so"
"/Applications/Mtk-1.5.0/lib/libMisrToolkit.so"

julia> v = ccall((:MtkVersion, mtklib), Cstring, ())
Cstring(0x000000014487a6f0)

julia> unsafe_string(v)
"1.5.0"

```

I then wanted to use the C function that converts an ISO 8601 date and time specification (“yyyy-mm-ddThh:mm:ssZ”) into a Julian day number, which features the following header:

```julia
MTKt_status MtkDateTimeToJulian(
  const char *datetime, /**< [IN] Date and time (ISO 8601) */
  double *jd /**< [OUT] Julian date */ )
{
    ...
}

```

However, the following call generates an error message (3) indicating an incorrect argument:

```julia
julia> dt = "2021-06-27T10:53:29Z"
"2021-06-27T10:53:29Z"

julia> status = ccall((:MtkDateTimeToJulian, mtklib), Cint, (AbstractString, Float64), dt, jd)
3

```

Reading through the documentation at

[https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/)

and in particular the paragraph entitled “When to use T, Ptr{T} and Ref{T}”, I tried to refer to the output argument `jd` as a pointer type, but got the following error messages:

```julia
julia> status = ccall((:MtkDateTimeToJulian, mtklib), Cint, (AbstractString, Ptr{Float64}), dt, jd)
ERROR: MethodError: no method matching unsafe_convert(::Type{Ptr{Float64}}, ::Float64)
Closest candidates are:
  unsafe_convert(::Type{Ptr{Tv}}, ::SuiteSparse.CHOLMOD.Sparse{Tv}) where Tv at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/SuiteSparse/src/cholmod.jl:296
  unsafe_convert(::Type{Ptr{T}}, ::SharedArrays.SharedArray{T, N} where N) where T at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/SharedArrays/src/SharedArrays.jl:361
  unsafe_convert(::Type{Ptr{T}}, ::SharedArrays.SharedArray) where T at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.6/SharedArrays/src/SharedArrays.jl:362
  ...
Stacktrace:
 [1] top-level scope
   @ ./REPL[32]:1

```

I suspect the problem is specifically related to the characterization of the output argument `jd`. Thanks in advance for any help in figuring out how to successfully call that C function from a Julia program.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 27, 2021, 11:49am UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/2 "2021-06-27T11:49:47Z")

</div>

> [@mmv](#):
>
> `double *jd`

This is a pointer to double, so

```julia
julia> jd_ref = Ref{Float64}(0.0)

julia> status = ccall((:MtkDateTimeToJulian, mtklib), Cint, (AbstractString, Ptr{Float64}), dt, jd_ref)

julia> jd = jd_ref[]

```

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 27, 2021, 11:58am UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/3 "2021-06-27T11:58:01Z")

</div>

@Gnimuc: Thanks for the quick answer. Here is the outcome:

```julia
julia> jd_ref = Ref{Float64}(0.0)
Base.RefValue{Float64}(0.0)

julia> status = ccall((:MtkDateTimeToJulian, mtklib), Cint, (AbstractString, Ptr{Float64}), dt, jd_ref)
3

julia> julia> jd = jd_ref[]
> (generic function with 1 method)

julia> jd = jd_ref[]
0.0

```

So the good point is that Julia does not complain about the `ccall` command, but I still get an error message (3, instead of 0), and the Julian day number is of course not 0 either. Any other thought?

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 27, 2021, 12:03pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/4 "2021-06-27T12:03:17Z")

</div>

`AbstractString` should be `Cstring`, I think.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 27, 2021, 12:05pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/5 "2021-06-27T12:05:20Z")

</div>

@Gnimuc: I had tried this too before, but it does not seem to make any difference:

```julia
julia> status = ccall((:MtkDateTimeToJulian, mtklib), Cint, (String, Ptr{Float64}), dt, jd_ref)
3

```

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 27, 2021, 12:06pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/6 "2021-06-27T12:06:05Z")

</div>

`Cstring` and `String` are different types.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 27, 2021, 12:11pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/7 "2021-06-27T12:11:14Z")

</div>

@Gnimuc: Indeed, I just realized after pressing the “Reply” button… Now I get a `0` status (no error) and everything works fine:

```julia
julia> status = ccall((:MtkDateTimeToJulian, mtklib), Cint, (Cstring, Ptr{Float64}), dt, jd_ref)
0

julia> jd_ref[]
2.4593929538078704e6

```

Just one last question: is this syntax `Ref{Float64}(0.0)` the generic way to declare an output argument before calling a C function? Should I do this with all output variables in general? Thanks again for your prompt and efficient help.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 27, 2021, 12:28pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/8 "2021-06-27T12:28:29Z")

</div>

> is this syntax `Ref{Float64}(0.0)` the generic way to declare an output argument before calling a C function?

Yes. If you need to use the content(`jd`) of this `Ref` variable(`jd_ref`), it’s necessary to init it in this way(i.e. bind `Ref(jd)` to a variable name(`jd_ref`)). If not, you could use a tmp variable like:

```julia
jd = 0
ccall((:MtkDateTimeToJulian, mtklib), Cint, (Cstring, Ptr{Float64}), dt, Ref(jd))
# this time, the content of the tmp variable `Ref(jd)` will be populated by the C function,
# but there is no way to get that content on the Julia side.
# jd is still 0. 

```

BTW, you might be interested in [`CBinding.jl`](https://github.com/analytech-solutions/CBinding.jl) and [`Clang.jl`](https://github.com/JuliaInterop/Clang.jl) which are two packages in the Julia ecosystem that can make life easier when calling C libs in Julia.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 27, 2021, 12:31pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/9 "2021-06-27T12:31:21Z")

</div>

@Gnimuc: Great! I’ll look at those two packages. Thanks again: your help is greatly appreciated.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 29, 2021, 2:17pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/10 "2021-06-29T14:17:17Z")

</div>

@Gnimuc: Sorry to bother you again, but I still have additional questions about using that C library… When I try to use the C function that converts a `Float64` Julian day number into a string instead, I always get a `MethodError: no method matching unsafe_convert...` error, no matter what I use to initially declare the output variable and to define the type of argument in the `ccall` itself. For reference, the header of that other C function is as follows:

```julia
MTKt_status MtkJulianToDateTime(
  double jd, /**< [IN] Julian date */
  char datetime[MTKd_DATETIME_LEN] /**< [OUT] Date and time (ISO 8601) */ )
{
...
}

```

where the identifier `MTKd_DATETIME_LEN` is initialized to the constant `28` in an included `.h` file. Now, using a syntax similar to the cases above:

```julia
julia> mtklib = "/Applications/Mtk-1.5.0/lib/libMisrToolkit.so"
"/Applications/Mtk-1.5.0/lib/libMisrToolkit.so"

julia> jd = 2.4593929538078704e6
2.4593929538078704e6

julia> julia> dt_ref = Ref{String}("")
Base.RefValue{String}("")

julia> status = ccall((:MtkJulianToDateTime, mtklib), Cint, (Float64, Cstring), jd, dt_ref)
ERROR: MethodError: Cannot `convert` an object of type Base.RefValue{String} to an object of type Cstring
Closest candidates are:
  convert(::Type{Cstring}, ::Union{Ptr{Int8}, Ptr{Nothing}, Ptr{UInt8}}) at c.jl:167
  convert(::Type{T}, ::T) where T at essentials.jl:205
Stacktrace:
 [1] cconvert(T::Type, x::Base.RefValue{String})
   @ Base ./essentials.jl:396
 [2] top-level scope
   @ ./REPL[5]:1

or

julia> status = ccall((:MtkJulianToDateTime, mtklib), Cint, (Float64, String), jd, dt_ref)
ERROR: MethodError: Cannot `convert` an object of type Base.RefValue{String} to an object of type String
Closest candidates are:
  convert(::Type{String}, ::String) at essentials.jl:210
  convert(::Type{T}, ::T) where T<:AbstractString at strings/basic.jl:231
  convert(::Type{T}, ::AbstractString) where T<:AbstractString at strings/basic.jl:232
  ...
Stacktrace:
 [1] cconvert(T::Type, x::Base.RefValue{String})
   @ Base ./essentials.jl:396
 [2] top-level scope
   @ ./REPL[6]:1

```

How should output character strings be defined BEFORE the `ccall` command, as well as WITHIN the arguments of that command?

Lastly, I have already noted that other C functions in that library declare output arguments as `char *arg` or `char **arg` (instead of simply `char arg`): how should those arguments be referred to, initially and within the `ccall`?

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 29, 2021, 3:19pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/11 "2021-06-29T15:19:16Z")

</div>

```julia
ccall((:MtkJulianToDateTime, mtklib), Cint, (Float64, Cstring), jd, dt_ref)

```

The `ccall` macro implicitly calls `Base.cconvert` for converting the types of **argvalues** (`jd`, `dt_ref`) to corresponding **argtypes** (`Float64`, `Cstring`).

The error `ERROR: MethodError: Cannot `convert` an object of type...` means Julia fails to find a pre-defined `cconvert` method. In the case above, it’s `Base.cconvert(Cstring, Ref{String}(""))`. Now we know the reason, but how to fix this?

IMO, the first step is to check whether **argtypes** are matched to those types used in C. Here is the function prototype of `MtkJulianToDateTime`:

```julia
MTKt_status MtkJulianToDateTime( double jd, char datetime[MTKd_DATETIME_LEN] );

```

The type of `datetime` is a constant char array, but it’s actually not. When it is used as the argument type in a function prototype, it actually decays to a char pointer `char *`, so the corresponding Julia type could be `Cstring` if it’s `NUL`-terminated or `Ptr{Cuchar}` if not. In practice, it’s OK to use `Ptr{Cuchar}` if we don’t know which is the case. You could refer to [the `Type Correspondences` section](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/#Type-Correspondences) for further details.

Another thing the C function prototype tells us is the size(`MTKd_DATETIME_LEN`) of `datetime`, so the C function `MtkJulianToDateTime` expects a pointer to a container that can be filled with `MTKd_DATETIME_LEN` chars. One way to do this in Julia is binding `dt_ref` to a `Vector` like `dt_ref = Vector{Cuchar}(undef, MTKd_DATETIME_LEN)`. A `Ref` with `NTuple{MTKd_DATETIME_LEN, Cuchar}` as its field type can also work, but it’s not easy to work with this type in Julia.

The final version:

```julia
jd = 2.4593929538078704e6
dt_chars = Vector{Cuchar}(undef, MTKd_DATETIME_LEN)
status = ccall((:MtkJulianToDateTime, mtklib), Cint, (Float64, Ptr{Cuchar}), jd, dt_chars)
dt = String(dt_chars)

```

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 29, 2021, 3:30pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/12 "2021-06-29T15:30:47Z")

</div>

For `char **arg`, it’s a container that is populated with `char *`s, so if it is an input argument, `Ptr{UInt8}[pointer("strings1"), pointer("strings2")]` with type `Vector{Ptr{UInt8}}` would be fine.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 29, 2021, 3:52pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/13 "2021-06-29T15:52:19Z")

</div>

@Gnimuc: Thanks for your continuing support. Here is the outcome:

```julia
julia> dt_chars = Vector{Cuchar}(undef, 28)
28-element Vector{UInt8}:
 0xe0
 0x68
 0x3c
 0x1b
 0x01
 0x00
 0x00
 0x00
 0x30
 0x53
    ⋮
 0x12
 0x01
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00
 0x00

julia> status = ccall((:MtkJulianToDateTime, mtklib), Cint, (Float64, Ptr{Cuchar}), jd, dt_chars)
0

julia> dt = String(dt_chars)
"2021-06-27T10:53:29Z\0\0\0\0\0\0\0\0"

```

which is the correct outcome. Is it possible to generalize this? I will generally not know in advance how long the output string will be, so what should I specify instead of `28` in this particular case?

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 29, 2021, 4:02pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/14 "2021-06-29T16:02:49Z")

</div>

There are several ways to do this: [read null terminated string from byte vector in julia - Stack Overflow](https://stackoverflow.com/questions/61264545/read-null-terminated-string-from-byte-vector-in-julia)

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 29, 2021, 4:15pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/15 "2021-06-29T16:15:59Z")

</div>

I added the generator script and generated the bindings using Clang.jl here:

> **[MISR-Toolkit/juliawrapper/lib at julia-binding · Gnimuc/MISR-Toolkit](https://github.com/Gnimuc/MISR-Toolkit/tree/julia-binding/juliawrapper/lib)**
>
> julia-binding/juliawrapper/lib

You could pick up one that matches your local platform or just copy-paste the code you need.

Note that, `Cchar` is used everywhere instead of `Cuchar`. When converting a `Vector{Cchar}` to a `String`, you need to convert `Vector{Cchar}` to `Vector{Cuchar}` firstly. But I guess something like this can also work:

```julia
jd = 2.4593929538078704e6
dt_chars = Vector{Cuchar}(undef, MTKd_DATETIME_LEN) # let `Base.cconvert` do the conversion for us   
status = ccall((:MtkJulianToDateTime, mtklib), Cint, (Float64, Ptr{Cchar}), jd, dt_chars)
dt = String(dt_chars)

```

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [June 29, 2021, 4:29pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/16 "2021-06-29T16:29:28Z")

</div>

@Gnimuc: Wow! How can you generate so much code for various platforms in so little time? Amazing…

I’ll definitely explore this solution, and thanks for the link to the very useful Stack Overflow page showing how to remove the null characters at the end of a string.

In the meantime, my earlier question was somewhat different: when I call an arbitrary C function that outputs a string variable, I generally do not know what length to expect. For instance, a function may return the path (directory) and filename of a data file, which might be 150 characters long, while another could return a paragraph of text. Should I declare the output variable as `dt_chars = Vector{Cuchar}(undef, 10000)` just to be on the safe side (but that seems wasteful of memory), or is there a way to tell Julia and/or C that the length of the output variable will only be known at run time?

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [June 29, 2021, 4:44pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/17 "2021-06-29T16:44:54Z")

</div>

We don’t know unless the C API tells us.

In the case of this library, it uses constant array types in the function prototype instead of pointers. I think the purpose here is to use those fixed-size array types to inform users that the size of the array can be safely set to certain compiler time constant macro values.

Different C libraries have different API styles for this problem. For example, some libraries may add another variable to the function prototype and users need to query the size of the container in advance.

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 2, 2022, 12:39am UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/18 "2022-12-02T00:39:15Z")

</div>

Hi @Gnimuc and colleagues,

I have hit a snag in my attempt to write Julia wrappers for the C functions contained in NASA’s MISR Toolkit available from [GitHub - nasa/MISR-Toolkit: an API facilitating the access of MISR standard product files](https://github.com/nasa/MISR-Toolkit). Specifically, the problematic function is `MtkSetRegionByPathBlockRange.c`, whose first few lines read as follows:

```nohighlight
#include "MisrSetRegion.h"
#include "MisrCoordQuery.h"
#include "MisrError.h"
#include "MisrUtil.h"
#include "MisrOrbitPath.h"
#include "MisrProjParam.h"

/** \brief Select region by path and block range
 *
 * \return MTK_SUCCESS if successful.
 *
 * \par Example:
 * In this example, we select the region on path 39 starting at block 50 and ending at block 60. 
 *
 * \code
 * MTKt_region region = MTKT_REGION_INIT;
 * status = MtkSetRegionByPathBlockRange(39, 50, 60, &region);
 * \endcode
 */

MTKt_status MtkSetRegionByPathBlockRange(
  int path_number, /**< [IN] Path */
  int start_block, /**< [IN] Start Block */
  int end_block, /**< [IN] End Block */
  MTKt_Region *region /**< [OUT] Region */ )
{
...
}

```

where the following macros are defined in the include files `MisrMapQuery.h` and `MisrSetRegion.h`:

```nohighlight
typedef struct {
  double lat; /**< Latitude in decimal degrees */
  double lon; /**< Longitude in decimal degrees */
} MTKt_GeoCoord;

#define MTKT_GEOCOORD_INIT { 0.0, 0.0 }

typedef struct {
  MTKt_GeoCoord ctr; /**< Center of region */
} MTKt_GeoCenter;

#define MTKT_GEOCENTER_INIT { MTKT_GEOCOORD_INIT }

typedef struct {
  double xlat; /**< Som x or latitude extent in meters */
  double ylon; /**< Som y or longitude extent in meters */
} MTKt_Extent;

#define MTKT_EXTENT_INIT { 0.0, 0.0 }

typedef struct {
  MTKt_GeoCenter geo; /**< Region center coordinate in geographic lat/lon */
  MTKt_Extent hextent; /**< Half of the region overall extent in meters (measured from geo.ctr) */
} MTKt_Region;

#define MTKT_REGION_INIT { MTKT_GEOCENTER_INIT, MTKT_EXTENT_INIT }

```

I have translated those macros in Julia as follows, and included them in the module MISRToolkit called below:

```nohighlight
Base.@kwdef mutable struct MTKt_GeoCoord
    lat::Cdouble = 0.0
    lon::Cdouble = 0.0
end
export MTKt_GeoCoord

mutable struct MTKt_GeoCenter
    ctr::MTKt_GeoCoord
end
export MTKt_GeoCenter

Base.@kwdef mutable struct MTKt_Extent
    xlat::Cdouble = 0.0
    ylon::Cdouble = 0.0
end
export MTKt_Extent

mutable struct MTKt_Region
    geo::MTKt_GeoCenter
    hextent::MTKt_Extent
end
export MTKt_Region

```

I have encapsulated that C function in a Julia function as follows, where the location of the shared library `mtklib` is also specified in the module `MISRToolkit`:

```nohighlight
function mtksetregionbypathblockrange!(misr_path, misr_block1, misr_block2, region)
    status = ccall((:MtkSetRegionByPathBlockRange, mtklib),
        MTKt_status,
        (Cint, Cint, Cint, Ptr{MTKt_Region}),
        misr_path, misr_block1, misr_block2, region)
    return status
end

```

and then created the test function

```nohighlight
function chk_mtksetregionbypathblockrange()
    misr_path = convert(Int32, 37)
    misr_block1 = convert(Int32, 32)
    misr_block2 = convert(Int32, 40)
    region = MTKt_Region[]
    status = mtksetregionbypathblockrange!(misr_path, misr_block1, misr_block2, region)
# println("typeof(region) = ", typeof(region))
# println("num. elements in region = ", length(region))
# for i in eachindex(region)
# println(i, region(i))
# end
    return status
end

```

I then re-start Julia and call that test function `chk_` three times consecutively, first with all three `println` statements commented out, then with the first one un-commented, and then the second one also un-commented. This last attempt always results in a segmentation fault which crashes Julia, as does the for loop to print the elements of region:

```nohighlight
michel@MicMac2:~$ jMtk
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.8.2 (2022-09-29)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> using MISRToolkit
[Info: Precompiling MISRToolkit [d1318645-6a27-4cd6-895f-df1b29e726af]

julia> status = chk_mtksetregionbypathblockrange()
MTK_SUCCESS::MTKt_status = 0x00000000

julia> using MISRToolkit

julia> status = chk_mtksetregionbypathblockrange()
typeof(region) = Vector{MTKt_Region}
MTK_SUCCESS::MTKt_status = 0x00000000

julia> using MISRToolkit

julia> status = chk_mtksetregionbypathblockrange()
typeof(region) = 
signal (11): Segmentation fault: 11
in expression starting at REPL[6]:1
jl_gc_pool_alloc_inner at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_gc_alloc at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
_new_array_ at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
_new_array at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
ijl_alloc_array_1d at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
Array at ./boot.jl:459 [inlined]
Dict at ./dict.jl:90
Set at ./set.jl:9 [inlined]
make_typealias at ./show.jl:531
show_typealias at ./show.jl:721
_show_type at ./show.jl:886
show at ./show.jl:881
unknown function (ip: 0x13d1b4566)
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
print at ./strings/io.jl:35
unknown function (ip: 0x13d1aeea6)
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
print at ./strings/io.jl:46
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
do_apply at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
println at ./strings/io.jl:75
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
println at ./coreio.jl:4
chk_mtksetregionbypathblockrange at /Users/michel/Codes/Julia/MISRToolkit/scripts/chk_mtksetregionbypathblockrange.jl:7
unknown function (ip: 0x13d1b4bb5)
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
do_call at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
eval_body at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_interpret_toplevel_thunk at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_toplevel_eval_flex at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_toplevel_eval_flex at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_toplevel_eval_flex at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
ijl_toplevel_eval_in at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
eval at ./boot.jl:368 [inlined]
eval_user_input at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-6.0/build/default-macmini-x64-6-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:151
repl_backend_loop at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-6.0/build/default-macmini-x64-6-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:247
start_repl_backend at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-6.0/build/default-macmini-x64-6-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:232
#run_repl#47 at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-6.0/build/default-macmini-x64-6-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:369
run_repl at /Users/julia/.julia/scratchspaces/a66863c6-20e8-4ff4-8a62-49f30b1f605e/agent-cache/default-macmini-x64-6.0/build/default-macmini-x64-6-0/julialang/julia-release-1-dot-8/usr/share/julia/stdlib/v1.8/REPL/src/REPL.jl:355
jfptr_run_repl_65939.clone_1 at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
#967 at ./client.jl:419
jfptr_YY.967_55066.clone_1 at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_f__call_latest at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
#invokelatest#2 at ./essentials.jl:729 [inlined]
invokelatest at ./essentials.jl:726 [inlined]
run_main_repl at ./client.jl:404
exec_options at ./client.jl:318
_start at ./client.jl:522
jfptr__start_36967.clone_1 at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/sys.dylib (unknown line)
ijl_apply_generic at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
true_main at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
jl_repl_entrypoint at /Applications/Julia-1.8.app/Contents/Resources/julia/lib/julia/libjulia-internal.1.dylib (unknown line)
Allocations: 5507277 (Pool: 5499187; Big: 8090); GC: 6
/Users/michel/Codes/Scripts/bash/jMtk: line 4: 1187 Segmentation fault: 11 julia --project=.
michel@MicMac2:~$ 

```

I suspect something is improperly setup, though the return code is zero in the first two cases. I was surprised that a probable error on my part could crash Julia with a segmentation fault… But why is it that I cannot inquire about the length of the variable `region`, which appears to be a `Vector`, and why would trying to print some information on the screen in the `chk_` function result in a segmentation fault? Thanks in advance for any suggestion on how to proceed, especially to retrieve the four numerical values of region after the `ccall`.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [December 3, 2022, 11:54am UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/19 "2022-12-03T11:54:26Z")

</div>

Hi @mmv, does the problem persist if you change `region = MTKt_Region[]` to `region_ref = Ref{MTKt_Region}();` and use `region = region_ref[]` after running the function `mtksetregionbypathblockrange!`?

Another problem is the usage of `mutable`:

```julia
Base.@kwdef mutable struct MTKt_GeoCoord
    lat::Cdouble = 0.0
    lon::Cdouble = 0.0
end
export MTKt_GeoCoord

mutable struct MTKt_GeoCenter
    ctr::MTKt_GeoCoord
end
export MTKt_GeoCenter

Base.@kwdef mutable struct MTKt_Extent
    xlat::Cdouble = 0.0
    ylon::Cdouble = 0.0
end
export MTKt_Extent

mutable struct MTKt_Region
    geo::MTKt_GeoCenter
    hextent::MTKt_Extent
end
export MTKt_Region

```

`MTKt_GeoCoord` is used in `MTKt_GeoCenter`. If `MTKt_GeoCoord` is a mutable struct, Julia does not inline it in the struct `MTKt_GeoCenter`. As a result, the size of `MTKt_GeoCenter` on the Julia side and the size of `MTKt_GeoCenter` on the C side does match, which leads to segment fault at run time. So, only `MTKt_Region` can be mutable in your example(here, I’m assuming it is not used in other structs).

---

<div class="post-metadata">

**Author:** ![mmv](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mmv/32/26323_2.png) [@mmv](https://discourse.julialang.org/u/mmv)\
**Post date:** [December 3, 2022, 5:02pm UTC](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643/20 "2022-12-03T17:02:04Z")

</div>

> [@Gnimuc](#):
>
> `region = region_ref[]`

Hi @Gnimuc,

Thanks for your feedback. I have updated the `chk_` function as follows:

```Julia
function chk_mtksetregionbypathblockrange()
    misr_path = convert(Int32, 37)
    misr_block1 = convert(Int32, 32)
    misr_block2 = convert(Int32, 40)
    region_ref = Ref{MTKt_Region}(); 
    status = mtksetregionbypathblockrange!(misr_path, misr_block1, misr_block2, region_ref)
    region = region_ref[]
    println("typeof(region) = ", typeof(region))
    println("num. elements in region = ", length(region))
    for i in eachindex(region)
        println(i, region(i))
    end
    return status
end

```

and then tried to use it in a new session, with the following result:

```julia
michel@MicMac2:~$ jMtk
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` | |
  | | |_| | | | (_| | | Version 1.8.2 (2022-09-29)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

julia> using MISRToolkit
[Info: Precompiling MISRToolkit [d1318645-6a27-4cd6-895f-df1b29e726af]

julia> status = chk_mtksetregionbypathblockrange()
ERROR: UndefRefError: access to undefined reference
Stacktrace:
 [1] getproperty
   @ ./Base.jl:38 [inlined]
 [2] unsafe_convert
   @ ./refvalue.jl:42 [inlined]
 [3] mtksetregionbypathblockrange!
   @ ~/Codes/Julia/MISRToolkit/src/mtksetregionbypathblockrange.jl:2 [inlined]
 [4] chk_mtksetregionbypathblockrange()
   @ MISRToolkit ~/Codes/Julia/MISRToolkit/scripts/chk_mtksetregionbypathblockrange.jl:6
 [5] top-level scope
   @ REPL[2]:1

julia> 

```

As far as the `typedef` definitions are concerned, my initial translation was attempting to stick to the original C code as much as possible. Nevertheless, I have subsequently implemented the following simpler interpretation, which by-passes the intermediary steps:

```julia
Base.@kwdef mutable struct MTKt_Region
    lat::Cdouble = 0.0
    lon::Cdouble = 0.0
    xlat::Cdouble = 0.0
    ylon::Cdouble = 0.0
end

```

but that led to exactly the same error message (starting from a new Julia session, because the nature of the struct MTKt\_Region cannot be modified)…

[Next page](https://discourse.julialang.org/t/calling-a-c-function-from-within-a-julia-program/63643.md?page=2)
