Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #99068
| Path | csiph.com!news.swapon.de!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail |
|---|---|
| From | Robert Latest <boblatest@yahoo.com> |
| Newsgroups | comp.lang.python |
| Subject | Why doesn't this method have access to its "self" argument? |
| Date | 19 Nov 2015 16:13:44 GMT |
| Lines | 120 |
| Message-ID | <db6apoFgvjlU1@mid.individual.net> (permalink) |
| X-Trace | individual.net aZK9a0k6VRHTIwCKzGyJJgd4hVCuuOMaOGEpVvGfONQiT0c6uk |
| Cancel-Lock | sha1:JgMK6wbLJGn6EK6tm+3I1Qc4FnY= |
| User-Agent | slrn/1.0.2 (Linux) |
| Xref | csiph.com comp.lang.python:99068 |
Show key headers only | View raw
Hi all,
I'm still trying to find a simple way to implement a method (but not the
full class) in C. Suggestions I have recived so far are good, but seem to be
over the top for such a (seemingly) simple problem. I came up with the idea
of implementing the class in Python, and just setting the method after the
actual class definition. See example below. The "py_method" is added to the
class later on, and it seems to become a proper method of the class (and its
instances) just as if it had been defined inside the class itself. Of course
it also has access to its "self" argument.
If I do the same thing with a method implemented in the external module
"cmethod", and I call that method on an instance, it gets passed a NULL
pointer as its "self" argument and so has no access to the instance's "data"
attribute.
I found a workaround using a wrapper method which calls a C function,
passing the instance as a separate argument. It works, and I cannot see any
disadvantage. It's just not as elegant as I'd like it to be, and I don't
understand WHY the C "method" doesn't receive a pointer to the Python
instance. Maybe somebody can clarify.
Here's what happens when I build, install and run the minimal example below:
rl@dc:~/c/cwsf/python_module$ python test.py
py_method(): <__main__.Test instance at 0xb71f5a2c>
c_method(): self at (nil)
c_function(): self at (nil), instance at 0xb71f5a2c
<__main__.Test instance at 0xb71f5a2c>
'Some data'
c_function(): self at (nil), instance at 0xb71f5a2c
<__main__.Test instance at 0xb71f5a2c>
'New Data'
rl@dc:~/c/cwsf/python_module$
Minimal example files:
========================== test.py ===================================
import cmethod
class Test():
def __init__(self):
self.data = "Some data"
def wrapper(self):
return cmethod.c_function(self)
def py_method(self):
print "py_method(): %s" % repr(self)
# add methods to the class "after the fact"
Test.py_method = py_method
Test.c_method = cmethod.c_method
foo = Test()
foo.py_method() # works as expected
foo.c_method() # is passed NULL in its self argument, why?
foo.wrapper() # works fine, updates "data" attribute
foo.wrapper() # works fine, sees updated "data" attribute
==================== cmethod.c =======================================
#include <Python.h>
#include <stdio.h>
static PyObject *c_method(PyObject *self, PyObject *args) {
(void) args; /* not used */
fprintf(stderr, "c_method(): self at %p\n",
(void*) self); /* always prints 0x0 */
Py_INCREF(Py_None);
return Py_None;
}
static PyObject *c_function(PyObject *self, PyObject *args) {
PyObject *instance;
PyObject *o;
/* Retrieve instance from wrapper through argument tuple: WORKS */
PyArg_UnpackTuple(args, "c_function", 1, 1, &instance);
fprintf(stderr, "c_function(): self at %p, instance at %p\n",
(void*) self, (void*) instance);
PyObject_Print(instance, stderr, 0); fputc('\n', stderr);
/* Get and set attributes of instance: WORKS */
o = PyObject_GetAttrString(instance, "data");
PyObject_Print(o, stderr, 0); fputc('\n', stderr);
PyObject_SetAttrString(instance, "data",
PyString_FromString("New Data"));
/* Side question: Do I have to DECREF "o"? */
Py_INCREF(Py_None);
return Py_None;
}
static PyMethodDef methods[] =
{
{"c_method", c_method, METH_VARARGS, "I want to be a class method"},
{"c_function", c_function, METH_VARARGS, "I am a function"},
{NULL, NULL, 0, NULL}
};
PyMODINIT_FUNC initcmethod(void)
{
(void) Py_InitModule("cmethod", methods);
}
======================== setup_cmethod.py ===========================
from distutils.core import setup, Extension
module1 = Extension('cmethod', sources = ['cmethod.c'])
setup (name = 'cmethod',
version = '0.1',
description = 'struggling to implement a class method in C',
ext_modules = [module1])
robert
Back to comp.lang.python | Previous | Next — Next in thread | Find similar | Unroll thread
Why doesn't this method have access to its "self" argument? Robert Latest <boblatest@yahoo.com> - 2015-11-19 16:13 +0000 Re: Why doesn't this method have access to its "self" argument? Chris Angelico <rosuav@gmail.com> - 2015-11-20 04:34 +1100 Re: Why doesn't this method have access to its "self" argument? Peter Otten <__peter__@web.de> - 2015-11-19 19:00 +0100 Re: Why doesn't this method have access to its "self" argument? dieter <dieter@handshake.de> - 2015-11-20 08:18 +0100
csiph-web