PYTHON-C-API Throws ImportError with symbol undefind

Viewed 22

I have a project of creating a spectral clustering algorith with C-API. I have the following files in my directory: spkmeans.c, spkmeans.h, spkmeansmodule.c, spkmeans.py, setup.py.

I import my functions from the C files with python with the following command:

from myspkmeans import kmeans, handle

however I get the following error:

< ImportError: /specific/a/home/cc/students/math/yuvalalter/project/final/myspkmeans.cpython-37m-x86_64-linux-gnu.so: undefined symbol: lnorm

This is my setup.py file:

from setuptools import setup, find_packages, Extension

setup(
    name="myspkmeans",
    ext_modules=[
        Extension("myspkmeans", sources=["spkmeansmodule.c", "spkmeans.c"])
    ]
)

This is my spkmeansmodule.c:

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include "spkmeans.h"


static PyObject* kmeans_pp_capi(PyObject *self, PyObject *args){
    int n, K, dim, max_iter, i, j;
    double eps;
    double **points, **mus;
    double *p, *d;
    PyObject *temp_points, *temp_mus, *item, *res, *value;
    if (!PyArg_ParseTuple(args, "iiiidOO", &n, &K, &dim, &max_iter, &eps, &temp_points, &temp_mus)){
        return NULL;
    }
    p = calloc(n*dim, sizeof(double));
    points = calloc(n, sizeof(double*));
    if (!p || !points){
        free(p);
        free(points);
        return NULL;
    }
    for (i=0; i<n; i++){
        points[i] = p+i*dim;
    }
    //This loop reads the nested python list of points and converts it to an array of arrays
    for (i=0; i<n; i++){
        for (j=0; j<dim; j++){
            item = PyList_GetItem(PyList_GetItem(temp_points, i), j); /*
 * adapted from stackoverflow in this question: https://stackoverflow.com/questions/39063112/passing-a-python-list-to-c-function-using-the-python-c-api*/
            points[i][j] = PyFloat_AsDouble(item);
        }
    }

    d = calloc(K*dim, sizeof(double));
    mus = calloc(K, sizeof(double*));
    if (!d || !mus){
        free(p);
        free(points);
        free(d);
        free(mus);
        return NULL;
    }
    for (i=0; i<K; i++){
        mus[i] = d+i*dim;
    }
//This loop reads the nested python list of initial cluster centers and converts it to an array of arrays
    for (i=0; i<K; i++){
        for (j=0; j<dim; j++){
            item = PyList_GetItem(PyList_GetItem(temp_mus, i), j);
            mus[i][j] = PyFloat_AsDouble(item);
        }
    }

    mus = k_means(points, K, max_iter, n, dim, mus, eps); //call the k_means function on all arguments
    free(points[0]);
    free(points);

    //create a python list of size K*dim containing all cluster centers calculated by k_means
    res = PyList_New(K*dim);
    for (i = 0; i < K; i++){
        for (j=0; j<dim; j++){
            value = Py_BuildValue("d", mus[i][j]);
            PyList_SetItem(res, (dim)*i + j, value);
        }
    }



    free(mus[0]);
    free(mus);
    return res;

}

static PyObject* py_handler_capi(PyObject *self, PyObject *args){
    int n, K, dim, i, j;
    double **points;
    double *p, *values;
    double **mat;
    char *goal;
    PyObject *temp_points, *item, *res, *value;
    if (!PyArg_ParseTuple(args, "iiiOs", &n, &K, &dim,  &temp_points, &goal)){
        return NULL;
    }
    p = calloc(n*dim, sizeof(double));
    points = calloc(n, sizeof(double*));
    if (!p || !points){
        free(p);
        free(points);
        return NULL;
    }
    for (i=0; i<n; i++){
        points[i] = p+i*dim;
    }
    //This loop reads the nested python list of points and converts it to an array of arrays
    for (i=0; i<n; i++){
        for (j=0; j<dim; j++){
            item = PyList_GetItem(PyList_GetItem(temp_points, i), j); /*
 * adapted from stackoverflow in this question: https://stackoverflow.com/questions/39063112/passing-a-python-list-to-c-function-using-the-python-c-api*/
            points[i][j] = PyFloat_AsDouble(item);
        }
    }

    if (strcmp(goal, "spk")!=0){
        handler(points, goal, n, dim);
        free(points[0]);
        free(points);
        return Py_BuildValue("i", 0);
    }

    else{
        mat = lnorm(points, n, dim);
        values = (double*)calloc(n, sizeof(double));
        mat = jacobi(mat, n, &values);
        free(points[0]);
        free(points);
        points = final_mat(mat, values, n, K);
        res = PyList_New(n*K);
        for (i = 0; i < n; i++){
            for (j=0; j<K; j++){
                value = Py_BuildValue("d", points[i][j]);
                PyList_SetItem(res, K*i + j, value);
            }
        }
        free_mat(points);
        return res;
    }
}


static PyMethodDef capiMethods[] = {
        {"kmeans",
                (PyCFunction) kmeans_pp_capi,
                     METH_VARARGS,
                        PyDoc_STR("Writing centroid of Kmeans++ to the stated output file")
        },
        {"handle",
                (PyCFunction) py_handler_capi,
                     METH_VARARGS,
                        PyDoc_STR("Gets the points and the goal from python and executes")
        },
        {NULL, NULL, 0, NULL}
};

static struct PyModuleDef moduledef = {
        PyModuleDef_HEAD_INIT,
        "myspkmeans",
        NULL,
        -1,
        capiMethods
};

PyMODINIT_FUNC
PyInit_myspkmeans(void){
    PyObject *m;
    m = PyModule_Create(&moduledef);
    if(!m){
        return NULL;
    }
    return m;
}


Would appreciate any help!

0 Answers
Related