0

I am trying to implement the c function "main" in a python script. I recieve a memory access violation when I call the function. I know the types of my variables match and there are no array bounds issues, so I am not sure what the fix is. C function

float main(int** data) {
    float pi = 3.14159265;
    int max_distance = 182;
    int thetas = 181;
    int accumulator[182][181] = {0};
    int i, j, k, r, m, theta1, radius1;
    int current_max = 0; // initialize current_max to the smallest integer value
    double angle;
    float slope1;
    float d;
    // For loops for iterating through the test array indices, a conditional to check for "hits", followed by a for loop for creating sinusoidal line
    for (i = 0; i < ROWS; i++) {
        k = 127 - i; // Numpy array vs cartesian coordinate (0,0) in numpy array ==> (0,y_max) in cartesian
        for (j = 0; j < COLS; j++) {
            if (i >= 0 && i < ROWS && j >= 0 && j < COLS && data[k][j] != 0) {
                for (m = 0; m < thetas; m++) {
                    angle = (double)(-(pi/2) + (m * pi/2) / 90); // calculating thetas for -pi/2 to pi/2
                    r = fabs((j) * (cos(angle)) + (k) * (sin(angle)) );
                    accumulator[(int) r][m]++;
                }

            }   

        }
            
    }
    // Iterating through every accumulator index, to get
    for (i = 0; i < max_distance; i++) {
        for (j = 0; j < thetas; j++) {
            if (accumulator[i][j] > current_max) {
                current_max = accumulator[i][j];
                radius1 = i;
                theta1 = j-90;
            }
        }
    }

    // Calculating the slope from top radius and theta
    angle = (double)(theta1 * pi / 180); // Converts to radians
    slope1 = (float)(tan(angle + (double)pi/2)); // Make the calculation
    return slope1;
}

Python script

import ctypes
from numpy.ctypeslib import ndpointer

# Declare the function signature (return type and argument types)
fun = ctypes.CDLL("C:/Coding_Projects/Hough_Proj/C/HoughTransform.dll")
fun.main.argtypes = [ndpointer(dtype=np.int32, ndim=2)]
fun.main.restype = ctypes.c_float
i = 0
while i < len(slopes):
    j = 0
    currentslopes = slopes[i]
    currenttest = tests[i]
    while j < 47:
        currentset = np.array(currenttest[j], dtype=np.int32)
        result = fun.main(currentset)
        currentslopes.append(result)
        j += 1
    i += 1
  • 1
    I don't think an ndpointer will be `int **`, but rather an `int *` in either column-major or row-major order. – AKX May 15 '23 at 15:44
  • Consider using something like [pybind11](https://pybind11.readthedocs.io/en/stable/) - it will be much less error-prone. – 0x5453 May 15 '23 at 15:45
  • [\[SO\]: How can i cast a double pointer ctype to numpy array? (@CristiFati's answer)](https://stackoverflow.com/a/58784385/4788546) , [\[SO\]: What is numpy.ctypeslib.as\_ctypes exacty doing (@CristiFati's answer)](https://stackoverflow.com/a/68505437/4788546). Also, a function named *main* might be confusing (and you might get surprises if wanting to link the *.dll* in an application). – CristiFati May 15 '23 at 16:04
  • 2
    Please consider renaming the C function to avoid confusing it with the `main` function of a program in a hosted environment. – Ian Abbott May 15 '23 at 16:06

1 Answers1

2

According to references such as this, multi-dimensional Numpy arrays are not passed as (e.g.) int **, but as int *.

You'd need

void main(int *data, size_t x, size_t y) {

and a suitably dimensioned and flagged ndpointer:

np.ctypeslib.ndpointer(dtype=np.int32, ndim=2, flags="C")

and then you also need into pass in the size of your array (x and y above), since you can't know the size from a pointer alone.

AKX
  • 152,115
  • 15
  • 115
  • 172