2

I have a python class A like this.

class A: 
   def __init__(self, name): 
       self.name = name

   def print_lastname(self, lastname): 
       print(lastname)

I have to call this code like this.

import B
a = B.A("hello")
a.print_lastname("John")

Currently, I need to use this A class from my C++ code. I have got this far.

Py_Initialize(); 
string hello = "hello"; 
PyObject *module, *attr, *arg; 
module = PyObject_ImportModule("B"); // import B
attr = PyObject_GetAttrString(module, "A"); // get A from B
arg = PyString_FromString(hello.c_str()); 
instance = PyInstance_New(attr, arg, NULL); // trying to get instance of A with parameter "hello"
Py_Finalize(); 

But I am getting error

Exception TypeError: 'argument list must be tuple' in module 'threading' from '/usr/lib64/python2.7/threading.pyc'

How can I achieve from import statement to a.print_name("John") from C++? Any help is appreciated.

1 Answer 1

6

I'm going to rewrite the Python class slightly, just so it uses both the argument and member variable.

# B.py - test module
class A:
    def __init__(self, name):
        self.name = name

    def print_message(self, message):
        print message + ' ' + self.name

As for the C++ part, almost everything looks okay. The error you're getting is because the argument to PyInstance_New should be a tuple. There are multiple ways to call functions or methods. Here is a complete example using one of them:

// test.c - test embedding.
void error_abort(void)
{
    PyErr_Print();
    exit(EXIT_FAILURE);
}

int main(int argc, char* argv[])
{
    PyObject* temp, * args, * attr, * instance;

    Py_Initialize();
    if (!(temp = PyString_FromString("John")))
        error_abort();
    if (!(args = PyTuple_Pack(1, temp)))
        error_abort();
    Py_DECREF(temp);

    if (!(temp = PyImport_ImportModule("B")))
        error_abort();
    if (!(attr = PyObject_GetAttrString(temp, "A")))
        error_abort();
    Py_DECREF(temp);

    if (!(instance = PyInstance_New(attr, args, NULL)))
        error_abort();
    if (!PyObject_CallMethod(instance, "print_message", "s", "Hello"))
        error_abort();

    Py_DECREF(args);
    Py_DECREF(attr);
    Py_DECREF(instance);
    Py_Finalize();
    return 0;
}

For more information see Python pure-embedding.

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

2 Comments

very awesome! Works like a charm.
Note that PyInstance_New is not available in Python 3.x.

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.