core icon indicating copy to clipboard operation
core copied to clipboard

C loader: Cannot pass array (int[]) from Python to C functions

Open Ayush-Vish opened this issue 4 months ago • 3 comments

🐛 Bug Report

When calling a C function that takes an array (e.g., int pixels[]) from Python via MetaCall, the arguments fail with a type mismatch error. Minimal example: Python code

from PIL import Image
import numpy as np
from metacall import metacall, metacall_load_from_file

# Load C file
metacall_load_from_file('c', ['main.c'])

def process_image(image_path, output_path):
    img = Image.open(image_path).convert("RGB")
    pixels = np.array(img, dtype=np.uint8)

    flat_pixels = pixels.flatten().tolist()

    # Call C functions
    brightness = metacall("calculate_brightness", flat_pixels, len(flat_pixels))
    metacall("apply_blur_filter", flat_pixels, img.width, img.height)

    print("Brightness:", brightness)

process_image("input.jpeg", "output.jpeg")

C code

#include <stdio.h>

void apply_blur_filter(int pixels[], int width, int height) {
    int size = width * height * 3;
    for (int i = 0; i < size; i++) {
        pixels[i] = pixels[i] / 2;
    }
    printf("C: Blur filter applied on %d pixels\n", size);
}

double calculate_brightness(int pixels[], int size) {
    long sum = 0;
    for (int i = 0; i < size; i++) {
        sum += pixels[i];
    }
    double avg = (double)sum / size;
    printf("C: Average brightness = %f\n", avg);
    return avg;
}

Error Output:

[Sat Aug 16 15:10:06] #452654 @Error : Type mismatch in when calling calculate_brightness in argument number 0 (expected (null) of type Invalid and received Array). Canceling call in order to avoid a segfault.
[Sat Aug 16 15:10:06] #452654 @Error : Type mismatch in when calling apply_blur_filter in argument number 0 (expected (null) of type Invalid and received Array). Canceling call in order to avoid a segfault.
Brightness: None

Expected Behavior

MetaCall should pass the Python list/NumPy array into the C function as an int[] (inout pointer), allowing modification and correct return values.

This seems related to missing inout pointer support in the C loader. I found that PR #568 addresses exactly this issue.

Current Behavior

Possible Solution

Steps to Reproduce

Context (Environment)

Detailed Description

Possible Implementation

Ayush-Vish avatar Aug 20 '25 15:08 Ayush-Vish

@Ayush-Vish I am working on it already.

viferga avatar Aug 28 '25 16:08 viferga

@Ayush-Vish I have few questions, do you want this to be as performant as possible, no?

MetaCall calls by value, it means if you pass a python array into a C function, it will copy the array.

If you want to pass it as a reference, we have to pass it as a PyCapsule, it's basically like a pointer. This will copy the reference (it's still calling by value), but it won't copy the array itself.

A part of performance, if you pass an array, there is also the issue that if you modify the array in C land, it won't be modified on python side, like you are doing in the function apply_blur_filter.

viferga avatar Aug 29 '25 14:08 viferga

@Ayush-Vish this is solved already, can you test it? Reinstall metacall with the latest published version.

viferga avatar Sep 04 '25 21:09 viferga