PyObject_SetAttrString - doesn't set instance attribute

J

Jason

I'm having a bit of trouble with C/Python bindings. Particularly,
trying to set an instance variable from C when the object is
initialised using PyObject_SetAttrString, but nothing seems to happen.
The C initialisation code is:

static void
nautilus_python_object_instance_init (NautilusPythonObject *object)
{

fprintf(stderr, "nautilus_python_object_instance_init called\n");

NautilusPythonObjectClass *class;
debug_enter();

class = (NautilusPythonObjectClass*)(((GTypeInstance*)object)-
g_class);

object->instance = PyObject_CallObject(class->type, NULL);

PyObject* test_int = PyInt_FromLong(42);

if (object->instance == NULL)
{
PyErr_Print();
}
else
{
fprintf(stderr, "Setting magic parameter\n");
fprintf(stderr, "From C: ");
PyObject_Print(object->instance, stderr, 0);
fprintf(stderr, "\n");
int retval = PyObject_SetAttrString(object->instance,
"super_happy_magic", test_int);
fprintf(stderr, "Result: %i\n", retval);
}

Py_DECREF(test_int);
}

....and the Python module contains:


class MenuProviderTest(nautilus.MenuProvider):

def __init__(self):
print "From Python: %s" % self

try:
print getattr(self, "super_happy_magic")
except AttributeError:
print "Didn't work!"

When the MenuProviderTest is created, the output is:

nautilus_python_object_instance_init called
Setting magic parameter
From C: <MenuProvTest.MenuProviderTest object at 0x7faee6a9fcd0>
Result: 0
From Python: <MenuProvTest.MenuProviderTest object at 0x7faee6a9fcd0>
Didn't work!

(I've tried getattr and self.super_happy_magic, with the same effect.)

Where am I going wrong?

— Jason
 
C

Carl Banks

I'm having a bit of trouble with C/Python bindings. Particularly,
trying to set an instance variable from C when the object is
initialised using PyObject_SetAttrString, but nothing seems to happen.
The C initialisation code is:

static void
nautilus_python_object_instance_init (NautilusPythonObject *object)
{

        fprintf(stderr, "nautilus_python_object_instance_init called\n");

        NautilusPythonObjectClass *class;
        debug_enter();

        class = (NautilusPythonObjectClass*)(((GTypeInstance*)object)-


        object->instance = PyObject_CallObject(class->type, NULL);

        PyObject* test_int = PyInt_FromLong(42);

        if (object->instance == NULL)
        {
                PyErr_Print();
        }
        else
        {
                fprintf(stderr, "Setting magic parameter\n");
                fprintf(stderr, "From C: ");
                PyObject_Print(object->instance, stderr, 0);
                fprintf(stderr, "\n");
                int retval = PyObject_SetAttrString(object->instance,
"super_happy_magic", test_int);
                fprintf(stderr, "Result: %i\n", retval);
        }

        Py_DECREF(test_int);

}

Not sure what you're doing here. It looks like you are being passed
an object of a given type, then you get the type object, call it to
create another object of that type, and assign it to object->instance.

...and the Python module contains:

class MenuProviderTest(nautilus.MenuProvider):

    def __init__(self):
        print "From Python: %s" % self

        try:
            print getattr(self, "super_happy_magic")
        except AttributeError:
            print "Didn't work!"

When the MenuProviderTest is created, the output is:

nautilus_python_object_instance_init called
Setting magic parameter
From C: <MenuProvTest.MenuProviderTest object at 0x7faee6a9fcd0>
Result: 0
From Python: <MenuProvTest.MenuProviderTest object at 0x7faee6a9fcd0>
Didn't work!

(I've tried getattr and self.super_happy_magic, with the same effect.)

Where am I going wrong?

You are assigning the attirbute the the object that the C code refers
to as "object->instance", but it seems that in the Python snippet you
are calling getattr on the object that the C code refers to as
"object".


Carl Banks
 
J

Jason

Not sure what you're doing here.  It looks like you are being passed
an object of a given type, then you get the type object, call it to
create another object of that type, and assign it to object->instance.

Sorry, I should have noted that the "NautilusPythonObject" type in the
code is a struct defined as:

struct _NautilusPythonObject {
GObject parent_slot;
PyObject *instance;
};
You are assigning the attirbute the the object that the C code refers
to as "object->instance", but it seems that in the Python snippet you
are calling getattr on the object that the C code refers to as
"object".

object->instance is the PyObject, and I gathered that it was the
correct thing to assign to from the fact that the address is identical
as seen from C and Python.

— Jason
 
C

Carl Banks

Sorry, I should have noted that the "NautilusPythonObject" type in the
code is a struct defined as:

struct _NautilusPythonObject {
  GObject parent_slot;
  PyObject *instance;

};

object->instance is the PyObject, and I gathered that it was the
correct thing to assign to from the fact that the address is identical
as seen from C and Python.

We'd have to see more code, I'd think. What you posted needs more
context. For instance, what type, exactly, is class->type? This
would help us understand better.

I don't understand how object->instance and self could be the same
object. If they have the same address it's possible (and, I'm
inclined to think, likely) that you're creating an object, it's
getting destroyed, then you are creating another one.

Here's what's really odd. You are calling getattr(self,
"super_happy_magic") inside __init__, which is the class's
initializer. How could you have had occasion to call
PyObject_SetAttrString on that same object at that point? The only
possible way it could have happened is if
nautilus_python_object_instance_init is invoked by
MenuProviderTest.__new__ somehow, but that doesn't make sense either.
You run PyObject_CallObject(class->type,NULL) to create object-
instance, but calling a type also calls the type's __init__ method.
So how is it that later the __init__ method is being called again on
the same object? Unless you're doing something very weird, it could
only mean it's a different object.

I doubt it'll fix all your problems, but one thing to try is to
replace "PyObject_CallObject(class->type, NULL);" with "class->type-
tp_new(class->type);".

But you probably have to go back to the drawing board and rethink the
whole thing. What you've posted is quite unusual.


You should choose more descriptive variable names, too.


Carl Banks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,089
Latest member
Ketologenic

Latest Threads

Top