gpt4 book ai didi

python - 如何在 Python C-API 中获取当前函数名称?

转载 作者:太空宇宙 更新时间:2023-11-03 13:04:57 24 4
gpt4 key购买 nike

我实现了一堆函数,它们是从 Python 解释器调用的同一个 C 函数中分派(dispatch)的:

PyObject *
CmdDispatch(PyObject *self, PyObject *args, PyObject *kwargs)

没想到self为NULL,需要获取当前调用的函数名。有什么办法可以得到这些信息吗?

我有几十个函数都通过这个例程。此命令将所有选项处理成 C++ 映射,并将其传递给每个命令的实现。

更新: http://docs.python.org/extending/extending.html#a-simple-example具体说“self 参数指向模块级函数的模块对象;对于方法它将指向对象实例。”,但是在针对 python 2.6 进行链接时我得到了 null。

最佳答案

我一直在尝试解决非常相似的问题。

我得出的结论表明,无法在 Python C API 级别确定当前函数或调用者的名称。原因是,Python 解释器仅将纯 Python 函数(在 Python 本身中实现)放在调用堆栈上。用 C 实现的函数,无论是否在模块方法表中注册,都不会放在 Python 堆栈中,因此不可能通过检查堆栈帧找到它们。

这是一个用 Python 编写的简单示例,说明了我想要实现的目标(我假设 Juan 要求类似的行为):

import sys
def foo():
print('foo:', sys._getframe(0).f_code.co_name)
def bar():
print('bar:', sys._getframe(0).f_code.co_name)
foo()
bar()

下面是这个例子的近似等价物(基于 Python 3 docs )但使用 Python C API 实现:

// Based on example from Python 3.2.1 documentation, 5.4. Extending Embedded Python
// http://docs.python.org/release/3.2.1/extending/embedding.html#extending-embedded-python
//
#include <Python.h>
#include <frameobject.h>

static void foo()
{
PyThreadState * ts = PyThreadState_Get();
PyFrameObject* frame = ts->frame;
while (frame != 0)
{
char const* filename = _PyUnicode_AsString(frame->f_code->co_filename);
char const* name = _PyUnicode_AsString(frame->f_code->co_name);
printf("foo: filename=%s, name=%s\n", filename, name);
frame = frame->f_back;
}
}

static void bar()
{
PyRun_SimpleString(
"import sys\n"
"print(\"bar: filename=%s, name=%s\" % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_code.co_name))"
);
}

static PyObject* emb_numargs(PyObject *self, PyObject *args)
{
foo();
bar();

PyRun_SimpleString(
"import sys\n"
"print(\"emb_numargs: filename=%s, name=%s\" % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_code.co_name))"
);

return PyLong_FromLong(0);
}

static PyMethodDef EmbMethods[] = {
{"numargs", emb_numargs, METH_VARARGS, "Return number 0"},
{NULL, NULL, 0, NULL}
};

static PyModuleDef EmbModule = {
PyModuleDef_HEAD_INIT, "emb", NULL, -1, EmbMethods,
NULL, NULL, NULL, NULL
};

static PyObject* PyInit_emb(void)
{
return PyModule_Create(&EmbModule);
}

int main(int argc, char* argv[])
{
PyImport_AppendInittab("emb", &PyInit_emb);
Py_Initialize();
PyRun_SimpleString(
"import emb\n"
"print('This is Zero: ', emb.numargs())\n"
);
Py_Finalize();
return 0;
}

我希望这也能完成 Ned 的回答。

关于python - 如何在 Python C-API 中获取当前函数名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6565764/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com