Py_InitModule copies the name but not the function pointer?
<p>When I register callbacks using <code>Py_InitModule</code>, and if I later change the function pointer in the structure to point to a new function, the new function is called. But if I change the name, the new name is not recognized.</p>

<pre><code>#include &lt;Python.h&gt;

PyObject* foo1(PyObject *self, PyObject *args)
{
    printf("foo1\n");
    Py_RETURN_NONE;
}

PyObject* foo2(PyObject *self, PyObject *args)
{
    printf("foo2\n");
    Py_RETURN_NONE;
}

int main()
{
    PyMethodDef methods[] = {
        { "foo", foo1, METH_VARARGS, "foo" },
        { 0, 0, 0, 0 }
    };

    Py_Initialize();
    Py_InitModule("foo", methods);
    PyRun_SimpleString("import foo\n");
    PyRun_SimpleString("foo.foo()\n");
    methods[0].ml_meth = foo2;
    PyRun_SimpleString("foo.foo()\n");
    methods[0].ml_name = "foo2";
    PyRun_SimpleString("foo.foo()\n");
    PyRun_SimpleString("foo.foo2()\n");
    return 0;
}
</code></pre>

<p>This gives the following output:</p>

<pre>foo1
foo2
foo2
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'module' object has no attribute 'foo2'</pre>

<p>This seems a very inconsistent behavior. I first encountered it when I used a stack variable for <code>PyMethodDef methods</code>, which crashed the program once the variable went out of scope and I still tried to call the C++ callback from python. So I tested that changing the pointer indeed changes which function is called even though I haven't re-registered it with another <code>Py_InitModule</code> call. But at the same time, changing the name does not have this behavior.</p>

<p>So far I'm pretty certain that <code>PyMethodDef</code> needs to live for as long as python code tries to call the methods (i.e. can't be stack/local variable), but only the function pointers themselves are used.</p>

<p>Is this an intentional behavior, or some oversight? The documentation doesn't mention anything about PyMethodDef lifetime that I could find.</p>

<p>The inconsistency you see arises from the difference between a function's code, which is the property of the function itself, and the name by which it is invoked from a module, which is the property of the module (key in its dict). While a function's name is also stored in the function object, it is only used for <code>repr</code> and is not a fundamental property of the function.</p>

<p>This is quite intentional, as it allows using the same function object in different places under different names - or even without name, if the function is stored in a container. This would not be possible if one could "rename" it just by changing a property of the function.</p>

<p>One can demonstrate this same difference using regular Python functions, like this:</p>

<pre><code>&gt;&gt;&gt; def add(a, b): return a + b
... 
&gt;&gt;&gt; def sub(a, b): return a - b
... 
&gt;&gt;&gt; add
&lt;function add at 0x7f9383127938&gt;  # the function has a name
&gt;&gt;&gt; add.__name__ = 'foo'
&gt;&gt;&gt; add                           # the name is changed, but...
&lt;function foo at 0x7f9383127938&gt;
&gt;&gt;&gt; foo                           # the change doesn't affect the module
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
NameError: name 'foo' is not defined
&gt;&gt;&gt; add.__code__ = sub.__code__   # we can change the code, though
&gt;&gt;&gt; add(2, 2)
0
</code></pre>

<p>As for your question in the comment: the method fields are not copied because <code>Py_InitModule</code> and related functions are designed to be called with statically allocated structures, creating copies of which would be a waste of space. Not copying them explains why changing the actual C callback in <code>ml_meth</code> changes the Python callable.</p>

python c++ python-embedding