Jl_alloc_array_1d failed when called from python

I’m trying to use the c interface to call Julia code from python, following the “embedding Julia” section of the manual. I’m having issues with jl_alloc_array_1d.

As an example, here is a simple c program that runs fine.

#include <julia.h>

void print(const double* array, size_t numel)
{
    for (size_t i = 0; i < numel; i++)
        printf("%f ", array[i]);
    printf("\n");
}

int main(int argc, char *argv[])
{
    jl_init();
    
    jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
    jl_array_t* x          = jl_alloc_array_1d(array_type, 10);

    double *xData = jl_array_data(x, double);
    size_t numel = jl_array_nrows(x);

    for (size_t i = 0; i < numel; i++)
        xData[i] = i;

    print(xData, numel);

    jl_function_t *func = jl_get_function(jl_base_module, "reverse!");
    jl_call1(func, (jl_value_t*)x);
    
    print(xData, numel);

    jl_atexit_hook(0);
    return 0;
}

Here is an attempt at doing the same thing in python:

import sys
import os
import ctypes

julia_dir = "..."  # julia path
lib_path = os.path.join(julia_dir, "lib", "libjulia.so")
julia = ctypes.CDLL(lib_path, ctypes.RTLD_GLOBAL)

julia.jl_init.argtypes = ()
julia.jl_init()

# jl_value_t *jl_apply_array_type(jl_value_t *type, size_t dim)
julia.jl_apply_array_type.argtypes = (ctypes.c_void_p, ctypes.c_size_t)
julia.jl_apply_array_type.restype = ctypes.c_void_p

array_type = julia.jl_apply_array_type(ctypes.cast(julia.jl_float64_type, ctypes.c_void_p), 1)

# jl_array_t *jl_alloc_array_1d(jl_value_t *atype, size_t nr)
julia.jl_alloc_array_1d.argtypes = (ctypes.c_void_p, ctypes.c_size_t)
julia.jl_alloc_array_1d.restype = ctypes.c_void_p
jl_array = julia.jl_alloc_array_1d(array_type, 10)

# void jl_atexit_hook(int status);
julia.jl_atexit_hook.argtypes = (ctypes.c_int,)
julia.jl_atexit_hook(0)

This dies with the following error:

fatal: error thrown and no exception handler available.
TypeError(func=:GenericMemory, context=“element type”, expected=Type, got=Core.CodeInfo(code=Float64, codelocs=Type{T} where T<:Tuple, ssavaluetypes=UndefVarError, ssaflags=OutOfMemoryError(), method_for_inference_limit_heuristics=GenericMemoryRef{isatomic, T, addrspace}.name, linetable=Core.PartialStruct, slotnames=GenericMemory{isatomic, T, addrspace} where addrspace where T where isatomic, slotflags=Core.Binding, slottypes=Core.SimpleVector, rettype=Function, parent=typeof(Core.IntrinsicFunction), edges=Any, min_world=0x00007f8fa455a3f0, max_world=0x00007f8fa44d3590, inferred=true, propagate_inbounds=true, has_fcall=true, nospecializeinfer=true, inlining=0x8f, constprop=0x7f, purity=0x0000, inlining_cost=0xa9c0))

Am suggestions for what I’m doing wrong here?