diff --git a/Linux/LargeVismodule.cpp b/Linux/LargeVismodule.cpp index bbc50d9..fefda4b 100644 --- a/Linux/LargeVismodule.cpp +++ b/Linux/LargeVismodule.cpp @@ -5,6 +5,23 @@ real *out_vec; LargeVis model; char *filename; +struct module_state { + PyObject *error; +}; + +#if PY_MAJOR_VERSION >= 3 +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) +#else +#define GETSTATE(m) (&_state) +static struct module_state _state; +#endif + +static PyObject *error_out(PyObject *m) { + struct module_state *st = GETSTATE(m); + PyErr_SetString(st->error, "something bad happened"); + return NULL; +} + static PyObject *Run(PyObject *self, PyObject *args) { long long out_dim = -1; @@ -94,7 +111,11 @@ static PyObject *LoadFromList(PyObject *self, PyObject *args) } for (long long j = 0; j < n_dim; ++j) { +#if PY_MAJOR_VERSION >= 3 + real x = atof(PyBytes_AS_STRING(PyUnicode_AsUTF8String(PyObject_Str(PyList_GetItem(vec, j))))); +#else real x = atof(PyString_AsString(PyObject_Str(PyList_GetItem(vec, j)))); +#endif data[ll + j] = x; } } @@ -116,6 +137,7 @@ static PyObject *SaveToFile(PyObject *self, PyObject *args) static PyMethodDef PyExtMethods[] = { + { "error_out", (PyCFunction)error_out, METH_NOARGS, NULL}, { "run", Run, METH_VARARGS, "(All arguments are optional.\nrun(output dimension, threads number, training samples, propagations number, learning rate, rp-trees number, negative samples number, neighbors number, gamma, perplexity)\nFire up LargeVis." }, { "loadfile", LoadFromFile, METH_VARARGS, "loadfile(str filename)\nLoad high-dimensional feature vectors from file." }, { "loadgraph", LoadFromGraph, METH_VARARGS, "loadfile(str filename)\nLoad graph from file." }, @@ -124,8 +146,58 @@ static PyMethodDef PyExtMethods[] = { NULL, NULL, 0, NULL } }; +#if PY_MAJOR_VERSION >= 3 + +static int Traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +static int Clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "LargeVis", + NULL, + sizeof(struct module_state), + PyExtMethods, + NULL, + Traverse, + Clear, + NULL +}; + +#define INITERROR return NULL + +PyMODINIT_FUNC PyInit_LargeVis(void) + +#else +#define INITERROR return + PyMODINIT_FUNC initLargeVis() +#endif { printf("LargeVis successfully imported!\n"); - Py_InitModule("LargeVis", PyExtMethods); +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&moduledef); +#else + PyObject *module = Py_InitModule("LargeVis", PyExtMethods); +#endif + if (module == NULL) + INITERROR; + struct module_state *st = GETSTATE(module); + + st->error = PyErr_NewException("myextension.Error", NULL, NULL); + if (st->error == NULL) { + Py_DECREF(module); + INITERROR; + } + +#if PY_MAJOR_VERSION >= 3 + return module; +#endif } diff --git a/Windows/LargeVismodule.cpp b/Windows/LargeVismodule.cpp index bbc50d9..fefda4b 100644 --- a/Windows/LargeVismodule.cpp +++ b/Windows/LargeVismodule.cpp @@ -5,6 +5,23 @@ real *out_vec; LargeVis model; char *filename; +struct module_state { + PyObject *error; +}; + +#if PY_MAJOR_VERSION >= 3 +#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) +#else +#define GETSTATE(m) (&_state) +static struct module_state _state; +#endif + +static PyObject *error_out(PyObject *m) { + struct module_state *st = GETSTATE(m); + PyErr_SetString(st->error, "something bad happened"); + return NULL; +} + static PyObject *Run(PyObject *self, PyObject *args) { long long out_dim = -1; @@ -94,7 +111,11 @@ static PyObject *LoadFromList(PyObject *self, PyObject *args) } for (long long j = 0; j < n_dim; ++j) { +#if PY_MAJOR_VERSION >= 3 + real x = atof(PyBytes_AS_STRING(PyUnicode_AsUTF8String(PyObject_Str(PyList_GetItem(vec, j))))); +#else real x = atof(PyString_AsString(PyObject_Str(PyList_GetItem(vec, j)))); +#endif data[ll + j] = x; } } @@ -116,6 +137,7 @@ static PyObject *SaveToFile(PyObject *self, PyObject *args) static PyMethodDef PyExtMethods[] = { + { "error_out", (PyCFunction)error_out, METH_NOARGS, NULL}, { "run", Run, METH_VARARGS, "(All arguments are optional.\nrun(output dimension, threads number, training samples, propagations number, learning rate, rp-trees number, negative samples number, neighbors number, gamma, perplexity)\nFire up LargeVis." }, { "loadfile", LoadFromFile, METH_VARARGS, "loadfile(str filename)\nLoad high-dimensional feature vectors from file." }, { "loadgraph", LoadFromGraph, METH_VARARGS, "loadfile(str filename)\nLoad graph from file." }, @@ -124,8 +146,58 @@ static PyMethodDef PyExtMethods[] = { NULL, NULL, 0, NULL } }; +#if PY_MAJOR_VERSION >= 3 + +static int Traverse(PyObject *m, visitproc visit, void *arg) { + Py_VISIT(GETSTATE(m)->error); + return 0; +} + +static int Clear(PyObject *m) { + Py_CLEAR(GETSTATE(m)->error); + return 0; +} + + +static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "LargeVis", + NULL, + sizeof(struct module_state), + PyExtMethods, + NULL, + Traverse, + Clear, + NULL +}; + +#define INITERROR return NULL + +PyMODINIT_FUNC PyInit_LargeVis(void) + +#else +#define INITERROR return + PyMODINIT_FUNC initLargeVis() +#endif { printf("LargeVis successfully imported!\n"); - Py_InitModule("LargeVis", PyExtMethods); +#if PY_MAJOR_VERSION >= 3 + PyObject *module = PyModule_Create(&moduledef); +#else + PyObject *module = Py_InitModule("LargeVis", PyExtMethods); +#endif + if (module == NULL) + INITERROR; + struct module_state *st = GETSTATE(module); + + st->error = PyErr_NewException("myextension.Error", NULL, NULL); + if (st->error == NULL) { + Py_DECREF(module); + INITERROR; + } + +#if PY_MAJOR_VERSION >= 3 + return module; +#endif }