python - 如果给定一个初始化类为 PyObject,则从 C++ 调用 Python 类方法
问题描述
我在 C++ 中有一个函数,它接收一个初始化的类作为 PyObject。python类是:
class Expression:
def __init__(self, obj):
self.obj = obj
def get_source(self):
#Check if the object whose source is being obtained is a function.
if inspect.isfunction(self.obj):
source = inspect.getsourcelines(self.obj)[0][1:]
ls = len(source[0]) - len(source[0].lstrip())
source = [line[ls:] for line in source]
#get rid of comments from the source
source = [item for item in source if item.lstrip()[0] != '#']
source = ''.join(source)
return source
else:
raise Exception("Expression object is not a function.")
C++ 收到这个:
Expression(somefunctogetsource)
从 c++ 如何调用表达式对象的 get_source 方法?到目前为止,我已经阅读了 python c-api 文档并尝试了这样的事情:
PyObject* baseClass = (PyObject*)expression->ob_type;
PyObject* func = PyObject_GetAttrString(baseClass, "get_source");
PyObject* result = PyObject_CallFunctionObjArgs(func, expression, NULL);
并将结果转换为字符串,但这不起作用。
解决方案
比你做的简单。您不需要直接从基类中检索任何内容。做就是了:
PyObject* result = PyObject_CallMethod(expression, "get_source", NULL);
if (result == NULL) {
// Exception occurred, return your own failure status here
}
// result is a PyObject* (in this case, it should be a PyUnicode_Object)
PyObject_CallMethod
接受一个对象来调用一个方法,一个 C 风格的字符串作为方法名称,一个格式字符串 + 可变参数作为参数。当不需要参数时,格式字符串可以是NULL
.
结果PyObject*
对 C++ 代码不是超级有用(它具有运行时确定的 1、2 或 4 字节字符,具体取决于所涉及的序数,因此直接将内存从它复制到std::string
或std::wstring
不起作用),但PyUnicode_AsUTF8AndSize
可以用于获取UTF-8 编码的版本和长度,可用于有效地构造std::string
具有等效数据的 a。
如果性能很重要,您可能希望在模块加载期间显式地进行PyObject*
表示"get_source"
,例如使用全局变量:
PyObject *get_source_name;
在模块中初始化PyMODINIT_FUNC
:
get_source_name = PyUnicode_InternFromString("get_source");
一旦你有了它,你可以使用更有效PyObject_CallMethodObjArgs
的:
PyObject* result = PyObject_CallMethodObjArgs(expression, get_source_name, NULL);
节省的主要是避免str
从 Cchar*
中一遍又一遍地构建 Python 级别,并且通过使用PyUnicode_InternFromString
来构造字符串,您正在使用实习字符串,从而提高查找效率(因为 nameget_source
本身在以下情况下会自动实习def
- ed 在解释器中,不会对内容进行实际的内存比较;它意识到这两个字符串都是实习的,只是检查它们是否指向相同的内存)。
推荐阅读
- java - 如何在 Java 中打印不同的参数多态方法?
- r - 在 R markdown Knitr HTML 输出中更改绘图大小以使所有内容可见时如何保持比率?
- google-analytics - 将增强的电子商务指标添加到查询中
- html - 如何将左侧的按钮与中心的链接对齐以形成可折叠的导航栏?
- r - 将存在-不存在矩阵转换为R中每行的单个变量
- google-maps - 我可以在带有选项滚轮的谷歌地图中使用滚动元素:真的吗?
- postgresql - 如何用包含相同选择语句的文件名替换 (select current_timestamp)?
- r - cronR cronjob 在 ubuntu/本地系统上工作,但不在 shinyapp.io 中
- c# - 如何修复“当前上下文中不存在名称‘k’”错误?
- visual-studio - 调试 ASP .Net Core 符号和源不匹配