Using ccall and pointer to pointer in linked list

Below is an example from K.N.King “C Programming” for a linked list, where add_to_list() acts pretty much like pushfirst!() of Julia:

#include <stdio.h>
#include <stdlib.h>

struct node {
    int value;
    struct node *next;
};

void add_to_list(struct node **list, int n) {
    struct node *new_node;
    new_node = malloc(sizeof(struct node));
    new_node->value = n;
    new_node->next = *list;
    *list = new_node;
}

int main() {
    struct node *list = NULL;
    add_to_list(&list, 10);
    add_to_list(&list, 20);

    printf("First value: %d\n", list->value); // print 20
    return 1;
}

To call this from Julia via ccall, I did the following:

const LIBLIST = joinpath(@__DIR__, "liblist")
ccall((:main, LIBLIST), Cint, ()) # works fine!

mutable struct Node 
    value :: Cint
    next :: Ptr{Node}
end

list = C_NULL
ccall((:add_to_list, LIBLIST), Cvoid, (Ptr{Ptr{Node}}, Cint), list, 10)
ccall((:add_to_list, LIBLIST), Cvoid, (Ptr{Ptr{Node}}, Cint), list, 20)

println("done")

which does not work with a segmentation fault error.

In Julia, how should I initialize list and how should I pass to add_to_list()?

Your julia list should not be C_NULL. Your C-code will dereference NULL value.

1 Like

Thanks, @tomaklutfu. Indeed it shouldn’t be NULL.

The following worked:


list_ref = Ref{Ptr{Node}}()

ccall((:add_to_list, LIBLIST), Cvoid, (Ptr{Ptr{Node}}, Cint), list_ref, 10)
ccall((:add_to_list, LIBLIST), Cvoid, (Ptr{Ptr{Node}}, Cint), list_ref, 20)

list = unsafe_load(list_ref[])
@show list.value # 20

This comment was helpful.