0

I've written a c++ method that enumerates the number of subgraphs of a specified size in a given adjacency matrix. I'm trying to make this method callable in python. The basic method signature takes a list and a number and (should) return a list of subgraphs, each one represented by a list of edges. The driver method looks like this:

// In python, this function will take two parameters
// arg1 - graph: An adjacency list
// arg2 - int: k, the subgraph size
extern "C" PyObject * enum_subgraphs(PyObject *self, PyObject *args)
{
  PyObject *graph;
  int k;
  if (!PyArg_ParseTuple(args, "Oi", &graph, &k)) return NULL;
  if (PyObject_Length(graph) < 0) return NULL;
  if (k <= 0) return NULL;

  // Hand the list to kavosh and initiialize connectivity list
  PyObject *connectivity = PyList_New(0);
  kavosh(graph, k, connectivity); // This is where all the real work is done
  return connectivity;
}

With the following setup in the same file:

static PyMethodDef CISE[] = {
  { "cise", enum_subgraphs, METH_VARARGS, "Enumerates subgraphs of adjacency list" },
  { NULL, NULL, 0, NULL }
};

DL_EXPORT(void) initcise(void)
{
  Py_InitModule("cise", CISE);
}

And then in setup.py

from setuptools import setup, Extension
# Compile *cise_python.cpp* into a shared library
setup(
ext_modules=[Extension('cise', ['cise_python.cpp'],),],
)

Everything at this point seems to compile and run fine (but I included them in case I made an error in their setup) at this point. However the following code will consistently fail:

from ctypes import *
import glob
libfile = glob.glob('build/*/cise*.so')[0]
c = CDLL(libfile)
c.enum_subgraphs.restype = py_object
c.enum_subgraphs.argtypes = [py_object, c_int]
graph = [[1, 2], [0, 2], [0, 1]]
c.enum_subgraphs(graph, 2)  # Segfault happens here

My guess is that the issue with what I've written lies with argtypes but everything I've found so far tells me that this is fine. As far as I am able to tell, the segmentation fault is immediate, so I don't believe the segfault is caused by my actual method implementation (which works perfectly fine with other data structures).

Any suggestions on what might be causing my program to crash would be greatly appreciated!

  • First step, replace `CDLL` with `PyDLL`. You can't call Python C API functions in a CDLL. – user2357112 Apr 04 '20 at 03:49
  • Actually, it looks like you were trying to write an extension module. You need to import that as a module, not mess with ctypes. – user2357112 Apr 04 '20 at 03:51
  • PyDLL still results in a segfault. How can I import my code as a module? Are there any good guides on this topic? I didn't know there was a difference. – Joshua Cragun Apr 04 '20 at 03:59
  • With `import`, same as any other module. (The import system does need to be able to find it, same as any other module.) – user2357112 Apr 04 '20 at 04:02
  • Ah yes that was the ticket! Once I managed to set up my module properly it worked perfectly! Thank you – Joshua Cragun Apr 04 '20 at 05:54

1 Answers1

0

Creating Python C Extension with this command

 python setup.py build_ext --inplace

Please setup your bind.c properly

Code Reference: bind.c a and PyMODINIT_FUNC and PyModuleDef

Dickens A S
  • 3,824
  • 2
  • 22
  • 45