2

I'm trying to use scikit learn in my C++ project. Here is the code I'm using:

    #include <Python.h>
    PyObject* loadModule(char* name)//
    {
        PyObject* pName = PyString_FromString(name);
        PyObject* pModule = PyImport_Import(pName);
        Py_DECREF(pName);
        return pModule;
    }
    void displayPyObject(PyObject* object)
    {

    PyObject* objectsRepresentation = PyObject_Repr(object);
    PyErr_Print();
    const char* s = PyString_AsString(objectsRepresentation);
    PyErr_Print();
    std::cout << "[ PYOBJECT ]" << s << std::endl;

    }
    //load functions/ attributes from module
    PyObject* loadComponentFromModule(char* module, char* component) 
    {
       PyObject* pModule = loadModule(module);
       PyObject* pyComponent = PyObject_GetAttrString(pModule, component);
       Py_DECREF(pModule);
       return pyComponent;
    }


   //WRAPPER FOR KMEANS CLUSTERING FROM SCIKIT-LEARN
class KMeans
{
public:
    KMeans(int nClusters)
    {

        PyObject* KmeansClass = loadComponentFromModule("sklearn.cluster", "KMeans");
        PyObject* pName2 = PyInt_FromLong((long) nClusters);
        PyObject* pArgs = PyTuple_New(1);
        PyTuple_SetItem(pArgs, 0, pName2);
        _Kcluster = PyObject_CallObject(KmeansClass, pArgs);
        _closestor = loadComponentFromModule("sklearn.metrics","pairwise_distances_argmin_min");
        Py_DECREF(KmeansClass);
        Py_DECREF(pName2);
        Py_DECREF(pArgs);
    }
    ~KMeans()
    {
        Py_DECREF(_Kcluster);
       Py_DECREF(_closestor);
    }

    void setNumClusters(int nClusters)
    {
        std::cout << "change to number cluster: " << nClusters << "\n";
        PyObject* nCluster = PyInt_FromLong((long) nClusters);
        int code = PyObject_SetAttrString(_Kcluster,"n_clusters", nCluster);
        PyErr_Print();
        if (code == -1)
        {
            std::cout << "[Error] KMeans.setNumClusters() Failed!! - Number of clusters didn't change!!\n";
        }
        Py_DECREF(nCluster);
    }




    void info()
    {
        displayPyObject(_Kcluster);
    }

private:
    PyObject* _Kcluster;
    //PyObject* _result;
    PyObject* _closestor;
};

PyObject* loadClassifier()
{
    PyObject* loader = loadComponentFromModule("sklearn.externals.joblib", "load");
    PyObject* pName2 = PyString_FromString("lda.pkl");
    PyObject* pArgs = PyTuple_New(1);
    PyTuple_SetItem(pArgs, 0, pName2);
    PyObject* clf = PyObject_CallObject(loader, pArgs);
    Py_DECREF(loader);
    Py_DECREF(pName2);
    Py_DECREF(pArgs);
//    displayPyObject(clf);
    return clf;
}

void produce_error()
{
    std::cout << "============================= LINE 0 =========================================\n";
    PyObject* clf = loadClassifier();//"sklearn.externals.joblib", "load");
    std::cout << "============================= LINE 1 =========================================\n";
    KMeans cluster(8);
    std::cout << "============================= LINE 2 =========================================\n";
    cluster.setNumClusters(5);
    std::cout << "============================= LINE 3 =========================================\n";
    cluster.info();
    std::cout << "============================= LINE 4 =========================================\n";

}

int main(int argc, char *argv[])
{
    Py_Initialize();
    produce_error();
    Py_Finalize();
    return 0;
}

Every time I run this program, I get the error:

============================= LINE 0 =========================================
============================= LINE 1 =========================================
Segmentation fault (core dumped)

As far as I understand, without calling the classifier, I don't get any error but whenever I call it (loadClassifier()) and create an instance of KMeans, the error is showed up. Sometime error is inside the constructor of KMeans where I load the module, with the same code in another function (which isn't here), the error is inside PyObject_Repr() (inside displayPyObject()).

Anyone get the same problem before? Do you know how to solve it? Thanks in advance.

1 Answer 1

2

Problem solved. I figured it out. So answer here for the future if someone needs. Becareful when you use Py_DECREF(). The problem comes from this line inside the constructor of KMeans:

Py_DECREF(pName2);

Because when you run the Py_DECREF(pArgs); it will try to free pName2 which already was freed. It will create a unpredictable behavior. After commented that line, everythings run ok.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.