Python C API:PyDateTime_FromTimestamp会导致分段错误
Python C API: PyDateTime_FromTimestamp causes segmentation fault
我按照这个答案调用PyDateTime_FromTimestamp
在C++中创建一个datetime
对象。但是当PyDateTime_FromTimestamp
被召唤时,我得到了一个Segmentation fault
。
这是我C++代码:
#include <python3.6/Python.h>
#include <stdio.h>
#include <python3.6/datetime.h>
#include <sys/time.h>
static PyObject *iGetDateTime_PyFn(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
static double doubleValue = 1314761451;
PyObject *floatObj = NULL;
PyObject *timeTuple = NULL;
PyObject *dateTime = NULL;
floatObj = PyFloat_FromDouble(doubleValue);
timeTuple = Py_BuildValue("(O)", floatObj);
printf("timeTuple = %08xn", (unsigned int)(long long)timeTuple);
printf("PyTuple_Check(timeTuple) = %dn", PyTuple_Check(timeTuple));
dateTime = PyDateTime_FromTimestamp(timeTuple);
printf("ready to returnn");
return dateTime;
}
static PyMethodDef all_methods[] = {
{ "get_datetime", iGetDateTime_PyFn, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
static struct PyModuleDef main_module = {
PyModuleDef_HEAD_INIT,
"cpp",
NULL,
-1,
all_methods
};
PyMODINIT_FUNC PyInit_cpp(void) {
return PyModule_Create(&main_module);
}
我用这个命令编译:
g++ --shared -fPIC -o cpp.so t1.cpp
我的g++
版本是7.3.0
.
在python中,我执行:
import cpp
print(cpp.get_datetime())
我打印了以下内容:
timeTuple = a7934358
PyTuple_Check(timeTuple) = 1
Segmentation fault (core dumped)
如我们所见,timeTuple
已成功构建,并被检查为tuple
。但是我们不能得到return
句子。
根据 [GitHub]: python/cpython - (3.6) cpython/Include/datetime.h (${PYTHON_SRC_DIR}/Include/datetime.h):
-
PyDateTime_FromTimestamp是一个预处理器宏:
#define PyDateTime_FromTimestamp(args) PyDateTimeAPI->DateTime_FromTimestamp( (PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL)
-
PyDateTimeAPI初始化为NULL(在文件的前面)
static PyDateTime_CAPI *PyDateTimeAPI = NULL;
在调用宏时导致段错误(访问冲突)。
该修复需要通过PyDateTime_IMPORT宏初始化PyDateTimeAPI。
#define PyDateTime_IMPORT
PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0)
最初,我在浏览代码时发现了这一点(我在getDateTimePyFn函数中做到了这一点),然后我遇到了[Python 3.Docs]:DateTime对象(重点是我的)
在使用任何这些函数之前,头文件
datetime.h
必须包含在源代码中(请注意,Python.h
不包含此功能),并且必须调用宏PyDateTime_IMPORT,通常作为模块初始化函数的一部分。
我修改了您的代码,我将在Win上举例说明(因为它对我来说更容易,并且行为是可重现的)。
CPP.C:
#include <stdio.h>
#include <Python.h>
#include <datetime.h>
#define MOD_NAME "cpp"
static double doubleValue = 1314761451;
static PyObject *getDateTimePyFn(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(args)) {
PyObject *floatObj = NULL,
*timeTuple = NULL,
*dateTime = NULL;
floatObj = PyFloat_FromDouble(doubleValue);
if (!floatObj)
{
return NULL;
}
timeTuple = Py_BuildValue("(O)", floatObj);
Py_XDECREF(floatObj);
if (!timeTuple)
{
return NULL;
}
dateTime = PyDateTime_FromTimestamp(timeTuple);
Py_XDECREF(timeTuple);
return dateTime;
}
static PyMethodDef all_methods[] = {
{ "get_datetime", getDateTimePyFn, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
static struct PyModuleDef main_module = {
PyModuleDef_HEAD_INIT,
MOD_NAME,
NULL,
-1,
all_methods
};
PyMODINIT_FUNC PyInit_cpp(void) {
PyDateTime_IMPORT; // @TODO - cfati: !!! This initializes the struct containing the function pointer !!!
return PyModule_Create(&main_module);
}
code.py:
#!/usr/bin/env python3
import sys
import cpp
def main():
print("cpp.get_datetime returned: {:}".format(cpp.get_datetime()))
if __name__ == "__main__":
print("Python {:s} on {:s}n".format(sys.version, sys.platform))
main()
print("Done.")
输出:
[cfati@CFATI-5510-0:e:WorkDevStackOverflowq055903897]> sopr.bat *** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages *** [prompt]> "c:Installx86MicrosoftVisual Studio Community2015vcvcvarsall.bat" x64 [prompt]> dir /b code.py cpp.c [prompt]> cl /nologo /DDLL /MD /I"c:Installx64PythonPython 3.06.08include" cpp.c /link /NOLOGO /DLL /LIBPATH:"c:Installx64PythonPython 3.06.08libs" /OUT:cpp.pyd cpp.c Creating library cpp.lib and object cpp.exp [prompt]> dir /b code.py cpp.c cpp.exp cpp.lib cpp.obj cpp.pyd [prompt]> "e:WorkDevVEnvspy_064_03.06.08_test0Scriptspython.exe" code.py Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32 cpp.get_datetime returned: 2011-08-31 06:30:51 Done.
相关文章:
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?