C Binding - how to pass pointer to a structure

I’m a Crystal newbie and I am trying to create my first C binding but there’s a few aspects I don’t quite understand…

First, how do I pass a pointer to a structure? This is what I’m attempting:

# the structure
struct XlsxDateTime
    year : Int32
    month : Int32
    day : Int32
    hour : Int32
    min : Int32
    sec : Float64
end

# the function signature
fun worksheet_write_datetime(worksheet : UInt64, row : UInt32, col : UInt16, datetime : XlsxDateTime*, format : UInt64) : UInt32

# and this is how I'm trying to call it
dt = Xlsx::XlsxDateTime.new
dt.day = 8
dt.month = 5
dt.year = 2025
Xlsx.worksheet_write_datetime(ws, row, col, Pointer(dt), fd)

But this gives the error:

630 | Xlsx.worksheet_write_datetime(ws, row, col, Pointer(dt), fd)
Error: unexpected token: "dt"

.
Also, what is the Crystal syntax when a C function expects a pointer to an array of structures as one of the parameters?

Pointer represents the type of a pointer, not how you obtain one. I think you’d want to leverage pointerof - Crystal, so something like:

Xlsx.worksheet_write_datetime(ws, row, col, pointerof(dt), fd)

Thank you, that’s now working :grin:

How do I declare a function that receives a pointer to an array of structures?
Here’s an example of a C declaration I want to wrap for Crystal:

lxw_error chart_series_set_labels_custom (lxw_chart_series *series, lxw_chart_data_label *data_labels[])

Source: libxlsxwriter: chart.h File Reference

The following two are the same

void func(struct Foo *bar[]);
void func(struct Foo **bar);

And in Crystal, it would look something like this

fun func(arr : Pointer(Pointer(Foo))) : Void
fun func(arr : Foo**) : Void

Another general tip is that lifetimes matter. So if you take a pointer to a local variable, then you must not let the current scope be invalidated. So especially when it comes to defining callbacks that is not an option, and instead you will probably want to define something like

def to_unsafe
  pointerof(@my_c_struct)
end