I'm working on a C++ extension for Python 3 and trying to pass a DateTime object to my function. the PyDateTime_Check function seems to work and returns true, but when I try to get the year from the DateTime object it returns 65535. I'm passing datetime.datetime.now() into the function from python.
my c++ code is:
#include "Python.h"
#include "datetime.h"
static PyObject* new_func(Pyobject* self, PyObject* args)
{
PyDateTime_DateTime *pydate;
if(!PyArg_ParseTuple(args, "O", &pydate)){
return Py_BuildValue("s", "Error");
}
int year;
year = PyDateTime_GET_YEAR(pydate);
return PyLong_FromLong(year);
}
static PyMethodDef NbourMethods[] =
{
{"new_func", new_func, METH_VARARGS, "Do date things."},
{NULL, NULL, 0, NULL}
};
static struct PyModuleDef cFunc =
{
PyModuleDef_HEAD_INIT,
"cFunc", /* name of module */
"", /* module documentation */
-1, /* size of per-interpreter state of the module or -1 if global */
NbourMethods
};
PyMODINIT_FUNC PyInit_cFunc(void)
{
if (!PyDateTimeAPI) { PyDateTime_IMPORT;}
return PyModule_Create(&cFunc);
}
Then my python code is:
import cFunc
start = datetime.datetime.now()
print(str(cFunc.new_func(start)))
Any thoughts? I'm able to successfully run PyDateTime_Check(pydate) and get a return value of true, but for some reason it won't return the year in the code above (returns 65535). Thanks in advance!
So after messing around some more there seemed to be an issue with both the compiler and the python library. Changing these yielded the desired results. I did have a weird hack below, but the extension module was using up about 4GB of RAM each time it was loaded -> indicating that there was something more wrong going on. Seems to be a potential issue in MinGW.
My original solution:
So just messing around and looking at the underlying datetime.h and doing some exploring - there seems to be 4 bytes in the PyObject for my date that are unused. Not sure why this is happening.
An interim fix is to return the year by referencing bytes 4 and 5 (as opposed to 0 and 1 in the function):
year = ((((PyDateTime_Date *)pydate)->data[4] << 8) | ((PyDateTime_Date *)pydate)->data[5]);
This isn't great, but an alternative would be to define my own GET_YEAR function after datetime.h is imported:
#define PyDateTime_GET_YEAR_NEW(o) ((((PyDateTime_Date*)o)->data[4] << 8) | \
((PyDateTime_Date*)o)->data[5])
Then the return in the function could be:
return PyLong_FromLong(PyDateTime_GET_YEAR_NEW(pydate));