6

I have a python module called my_module, within it I have a class called my_class and my_class has a classmethod called my_method.

Based on other examples I have seen around I have come up with the following attempts to call my_method from C++ but at present all of them return NULL (actually one of them segfaults...)

Firstly I import the module and class:

PyObject* my_module_name = PyString_FromString((char*)"my_module");
PyObject* myModule = PyImport_Import(my_module_name);

PyObject* my_class = PyObject_GetAttrString(myModule2, (char*)"my_class");
if (!my_class) std::cout << "my_class failed " << std::endl;

I then build the args for passing in as a tuple:

// These are the args
PyObject* my_args = PyTuple_Pack(
    5,
    PyString_FromString((char*)"first string"),
    PyString_FromString((char*)"next string"),
    PyFloat_FromDouble(0.0),
    PyFloat_FromDouble(1.0),
    Py_False
);
if (!my_args) std::cout << "my_args failed " << std::endl;

Then I try to call the actual method

PyObject* my_method = PyObject_GetAttrString(my_class,(char*)"my_method");
if (!my_method) std::cout << "failed " << std::endl;

// This returns NULL
PyObject* result_1 = PyObject_CallMethod(my_class, (char*)"my_method", "ssiib", my_args);
if (!result_1) std::cout << "failed result_1 " << std::endl;

// This returns NULL
PyObject* result_2 = PyObject_CallMethod(my_class, (char*)"my_method", "ssiib", my_args);
if (!result_2) std::cout << "failed result_2 " << std::endl;

// This returns NULL
PyObject* result_3 = PyObject_CallMethod(my_class, (char*)"my_method", "ssiib", "first string", "second string", 0.0, 1.0);
if (!result_3) std::cout << "failed result_3 " << std::endl;

// This one segfaults
PyObject* result_4 = PyObject_CallMethodObjArgs(my_class, my_method, my_args);
if (!result_4) std::cout << "failed result_4 " << std::endl;

// This returns NULL
PyObject* result_5 = PyObject_CallObject(my_method, my_args);
if (!result_5) std::cout << "failed result_5" << std::endl;

But they return NULL or in the case of attempt number 4, segfault.

I'm at a loss for what to try next so any help would be greatly appreciated.

Cheers, Jack

JMzance
  • 1,704
  • 4
  • 30
  • 49
  • It seems like `my_class` is a reference to the class object itself, but in general a class method is a function of a class *instance* object, not the class object itself. For example, `upper()` is a method for the class/type `str`, but you call it as `'my string'.upper()`, not `str.upper()`. Can you post your python class as well? – Steve Sep 29 '16 at 22:23
  • 1
    @Steve I think `my_method` is defined with `@classmethod`, and it should be available from the class and not just an instance. – DavidW Sep 30 '16 at 08:25
  • 2
    @JMzance. The calls for `result_1` and `result_2` are wrong. The way you call it in `result_3` is correct. `result_4` should be `PyObject_CallMethodObjArgs(my_class,"my_method",my_args,NULL)` (to pass a tuple as the first argument and no other arguments). Have you checked to see if a Python exception was thrown https://docs.python.org/2/c-api/exceptions.html - that could give you a clue what's going wrong... – DavidW Sep 30 '16 at 08:32

0 Answers0