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!