gpt4 book ai didi

Python C API : PyDateTime_FromTimestamp causes segmentation fault

转载 作者:行者123 更新时间:2023-11-28 01:21:43 26 4
gpt4 key购买 nike

我关注了this answer调用 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 = %08x\n", (unsigned int)(long long)timeTuple);
printf("PyTuple_Check(timeTuple) = %d\n", PyTuple_Check(timeTuple));
dateTime = PyDateTime_FromTimestamp(timeTuple);
printf("ready to return\n");
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):

  1. PyDateTime_FromTimestamp 是一个预处理器:

    #define PyDateTime_FromTimestamp(args) \
    PyDateTimeAPI->DateTime_FromTimestamp( \
    (PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL)
  2. 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 Objects (重点是我的)

Before using any of these functions, the header file datetime.h must be included in your source (note that this is not included by Python.h), and the macro PyDateTime_IMPORT must be invoked, usually as part of the module initialization function.

我修改了你的代码,我将在 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);
}

代码.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:\Work\Dev\StackOverflow\q055903897]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64

[prompt]> dir /b
code.py
cpp.c

[prompt]> cl /nologo /DDLL /MD /I"c:\Install\x64\Python\Python\03.06.08\include" cpp.c /link /NOLOGO /DLL /LIBPATH:"c:\Install\x64\Python\Python\03.06.08\libs" /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:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.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.

关于Python C API : PyDateTime_FromTimestamp causes segmentation fault,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55903897/

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