8000 fix segfault on exit with python3 by amadeus84 · Pull Request #301 · lava/matplotlib-cpp · GitHub
[go: up one dir, main page]

Skip to content

fix segfault on exit with python3 #301

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
style: from now on use Stroupstrup clang format from https://github.c…
…om/SoultatosStefanos/strstyle.git

       * the .clang-format file is committed here in the local directory
       * clang-format --style=file -i matplotlibcpp.h
  • Loading branch information
amadeus84 committed Mar 26, 2022
commit 231138afd7170bb19d5325084dcc2c7e286100c8
83 changes: 83 additions & 0 deletions .clang-format
8000
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignConsecutiveMacros: AcrossEmptyLinesAndComments
AlignEscapedNewlines: Right
AlignTrailingComments: false
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Always
AllowShortCaseLabelsOnASingleLine: false
AllowShortEnumsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: true
AllowShortLambdasOnASingleLine: All
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: No
BinPackArguments: true
BinPackParameters: true
BitFieldColonSpacing: Both
BreakBeforeBraces: Custom
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterFunction: true
AfterControlStatement: false
SplitEmptyFunction: false
AfterEnum: false
AfterNamespace: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: true
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: All
BreakBeforeConceptDeclarations: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
BreakStringLiterals: true
ColumnLimit: 80
CompactNamespaces: false
Cpp11BracedListStyle: true
DerivePointerAlignment: false
EmptyLineBeforeAccessModifier: Never
FixNamespaceComments: true
IncludeBlocks: Merge
IndentCaseLabels: false
IndentExternBlock: Indent
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
NamespaceIndentation: All
PointerAlignment: Left
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: false
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: Never
SpaceBeforeRangeBasedForLoopColon: false
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesInCStyleCastParentheses: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
UseTab: Never
149 changes: 69 additions & 80 deletions datetime_utils.h
Original file line number Diff line number Diff line change
@@ -1,138 +1,127 @@
#pragma once

#include "matplotlibcpp.h"

#include <Python.h>
#include <datetime.h>

#include <string>
#include <chrono>
#include <cstdlib>
#include <datetime.h>
#include <map>
#include <ranges>
#include <chrono>
#include <string>

// Convenience functions for converting C/C++ time objects to datetime.datetime
// objects. These are outside the matplotlibcpp namespace because they do not
// exist in matplotlib.pyplot.
template<class TimePoint>
PyObject* toPyDateTime(const TimePoint& t, int dummy=0)
PyObject* toPyDateTime(const TimePoint& t, int dummy = 0)
{
using namespace std::chrono;
auto tsec=time_point_cast<seconds>(t);
auto us=duration_cast<microseconds>(t-tsec);
auto tsec = time_point_cast<seconds>(t);
auto us = duration_cast<microseconds>(t - tsec);

time_t tt=system_clock::to_time_t(t);
PyObject* obj=toPyDateTime(tt, us.count());
time_t tt = system_clock::to_time_t(t);
PyObject* obj = toPyDateTime(tt, us.count());

return obj;
}

template <>
PyObject* toPyDateTime(const time_t& t, int us)
template<> PyObject* toPyDateTime(const time_t& t, int us)
{
tm tm {};
gmtime_r(&t,&tm); // compatible with matlab, inverse of datenum.
tm tm{};
gmtime_r(&t, &tm); // compatible with matlab, inverse of datenum.

if (!PyDateTimeAPI) {
PyDateTime_IMPORT;
}
if(!PyDateTimeAPI) { PyDateTime_IMPORT; }

PyObject* obj=PyDateTime_FromDateAndTime(tm.tm_year+1900,
tm.tm_mon+1,
tm.tm_mday,
tm.tm_hour,
tm.tm_min,
tm.tm_sec,
us);
if (obj) {
PyDateTime_Check(obj);
Py_INCREF(obj);
PyObject* obj = PyDateTime_FromDateAndTime(tm.tm_year + 1900, tm.tm_mon + 1,
tm.tm_mday, tm.tm_hour,
tm.tm_min, tm.tm_sec, us);
if(obj) {
PyDateTime_Check(obj);
Py_INCREF(obj);
}

return obj;
}

template <class Time_t>
PyObject* toPyDateTimeList(const Time_t* t, size_t nt)
template<class Time_t> PyObject* toPyDateTimeList(const Time_t* t, size_t nt)
{
PyObject* tlist=PyList_New(nt);
if (tlist==nullptr)
return nullptr;
PyObject* tlist = PyList_New(nt);
if(tlist == nullptr) return nullptr;

// Py_INCREF(tlist);

if (!PyDateTimeAPI) {
PyDateTime_IMPORT;
}
if(!PyDateTimeAPI) { PyDateTime_IMPORT; }

for (size_t i=0; i<nt; i++) {
PyObject* ti=toPyDateTime(t[i], 0);
PyList_SET_ITEM(tlist, i, ti);
for(size_t i = 0; i < nt; i++) {
PyObject* ti = toPyDateTime(t[i], 0);
PyList_SET_ITEM(tlist, i, ti);
}

return tlist;
}

template <class Time_t>
class DateTimeList
{
template<class Time_t> class DateTimeList {
public:

DateTimeList(const Time_t* t, size_t nt) {
tlist=(PyListObject*) toPyDateTimeList(t, nt);
DateTimeList(const Time_t* t, size_t nt)
{
tlist = (PyListObject*)toPyDateTimeList(t, nt);
}

~DateTimeList() { if (tlist) Py_DECREF((PyObject*) tlist); }
~DateTimeList()
{
if(tlist) Py_DECREF((PyObject*)tlist);
}

PyListObject* get() const { return tlist; }
size_t size() const { return tlist ? PyList_Size((PyObject*)tlist) : 0; }

private:
mutable PyListObject* tlist=nullptr;
mutable PyListObject* tlist = nullptr;
};



namespace matplotlibcpp {

// special purpose function to plot against python datetime objects.
template <class Time_t, std::ranges::contiguous_range ContainerY>
bool plot(const DateTimeList<Time_t>& t, const ContainerY& y,
const std::string& fmt="")
namespace matplotlibcpp
{
detail::_interpreter::get();

// DECREF decrements the ref counts of all objects in the plot_args tuple,
// In particular, it decreasesthe ref count of the time array x.
// We want to maintain that unchanged though, so we can reuse it.
PyListObject* tarray=t.get();
Py_INCREF(tarray);
// special purpose function to plot against python datetime objects.
template<class Time_t, std::ranges::contiguous_range ContainerY>
bool plot(const DateTimeList<Time_t>& t, const ContainerY& y,
const std::string& fmt = "")
{
detail::_interpreter::get();

NPY_TYPES ytype=detail::select_npy_type<typename ContainerY::value_type>::type;
// DECREF decrements the ref counts of all objects in the plot_args
// tuple, In particular, it decreasesthe ref count of the time array x.
// We want to maintain that unchanged though, so we can reuse it.
PyListObject* tarray = t.get();
Py_INCREF(tarray);

npy_intp tsize=PyList_Size((PyObject*)tarray);
assert(y.size()%tsize == 0 && "length of y must be a multiple of length of x!");
NPY_TYPES ytype
= detail::select_npy_type<typename ContainerY::value_type>::type;

npy_intp yrows=tsize, ycols=y.size()/yrows;
npy_intp ysize[]={yrows, ycols}; // ysize[0] must equal tsize
npy_intp tsize = PyList_Size((PyObject*)tarray);
assert(y.size() % tsize == 0
&& "length of y must be a multiple of length of x!");

PyObject* yarray = PyArray_New(&PyArray_Type,
2, ysize, ytype, nullptr, (void*) y.data(),
0, NPY_ARRAY_FARRAY, nullptr); // col major
npy_intp yrows = tsize, ycols = y.size() / yrows;
npy_intp ysize[] = {yrows, ycols}; // ysize[0] must equal tsize

PyObject* pystring = PyString_FromString(fmt.c_str());
PyObject* yarray = PyArray_New(&PyArray_Type, 2, ysize, ytype, nullptr,
(void*)y.data(), 0, NPY_ARRAY_FARRAY,
nullptr); // col major

PyObject* plot_args = PyTuple_New(3);
PyTuple_SetItem(plot_args, 0, (PyObject*)tarray);
PyTuple_SetItem(plot_args, 1, yarray);
PyTuple_SetItem(plot_args, 2, pystring);
PyObject* pystring = PyString_FromString(fmt.c_str());

PyObject* res = PyObject_CallObject(detail::_interpreter::get().s_python_function_plot, plot_args);
PyObject* plot_args = PyTuple_New(3);
PyTuple_SetItem(plot_args, 0, (PyObject*)tarray);
PyTuple_SetItem(plot_args, 1, yarray);
PyTuple_SetItem(plot_args, 2, pystring);

Py_DECREF(plot_args);
if(res) Py_DECREF(res);
PyObject* res = PyObject_CallObject(
detail::_interpreter::get().s_python_function_plot, plot_args);

return true;
}
Py_DECREF(plot_args);
if(res) Py_DECREF(res);

}
return true;
}

} // namespace matplotlibcpp
Loading
0