Согласно [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;
, что приводит к segfault ( Access)Нарушение ) при вызове макроса.
исправление требует инициализации PyDateTimeAPI через PyDateTime_IMPORT макрос.
#define PyDateTime_IMPORT \
PyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import(PyDateTime_CAPSULE_NAME, 0)
Сначала я обнаружил это во время просмотра кода (и сделал это в функции getDateTimePyFn ), затем я наткнулся на [Python 3.Docs]: DateTime Objects ( выделение принадлежит мне)
Перед использованием любой из этих функций файл заголовка 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:\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.