Skip to content

Commit b3b7579

Browse files
committed
Saner Memory Management + Fix Error Handling, Confirmed working on macOS
1 parent 69b261c commit b3b7579

File tree

6 files changed

+29
-68
lines changed

6 files changed

+29
-68
lines changed

Makefile

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,25 @@ SOURCES = $(SRC_DIR)/libparse_wrap.cpp $(SRC_DIR)/py_iostream.cpp $(SRC_DIR)/lib
66
OBJECTS = $(patsubst %.cpp,%.o,$(SOURCES))
77
HEADERS = $(SRC_DIR)/libparse.h $(SRC_DIR)/py_iostream.h $(SRC_DIR)/stdio_filebuf.h
88

9-
CXX = clang++
9+
CXXFLAGS += -g -std=c++11 -I$(shell python3 -c "import sysconfig; print(sysconfig.get_path('include'))")
10+
LDFLAGS += -g -L$(shell python3 -c "import sysconfig; print(sysconfig.get_path('stdlib'))")
11+
EXT = .so
1012

11-
CXXFLAGS += -stdlib=libc++ -g -std=c++11 -I$(shell python3 -c "import sysconfig; print(sysconfig.get_path('include'))")
13+
ifeq ("$(shell uname)", "Darwin")
14+
LDFLAGS += -dynamic -undefined dynamic_lookup
15+
else
16+
LDFLAGS += -shared
17+
endif
1218

13-
14-
all: _libparse.so
19+
all: _libparse$(EXT)
1520
patch: $(SRC_DIR)/libparse.cpp $(SRC_DIR)/libparse.h
1621
swig_out: $(SWIG_OUT)
1722

18-
_libparse.so: $(OBJECTS)
19-
$(CXX) -shared $^ -o $@
23+
_libparse$(EXT): $(OBJECTS)
24+
$(CXX) $(LDFLAGS) $^ -o $@
2025

2126
$(OBJECTS): %.o : %.cpp $(HEADERS)
22-
$(CXX) -fPIC -o $@ -c $(CXXFLAGS) -DFILTERLIB $<
27+
$(CXX) $(CXXFLAGS) -fPIC -o $@ -c -DFILTERLIB $<
2328

2429
$(SWIG_OUT): $(SWIG_IN) $(HEADERS)
2530
swig -c++ -o $(SRC_DIR)/libparse_wrap.cpp -oh $(SRC_DIR)/libparse.h -python $<

libparse/libparse.i

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,10 @@
2121

2222
%typemap(in) std::istream& {
2323
try {
24-
$1 = new PyIStream($input);
24+
$1 = PyIStream::make_from($input);
2525
} catch (std::runtime_error &e) {
26-
PyErr_SetString(PyExc_TypeError, e.what());
26+
std::cerr << e.what() << std::endl;
27+
SWIG_exception(SWIG_TypeError, e.what());
2728
}
2829
}
2930

libparse/py_iostream.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
#include "py_iostream.h"
22

3-
buffer_pair from_pyobject(PyObject *pyfile)
3+
PyIStream *PyIStream::make_from(PyObject *pyfile)
44
{
55
if (pyfile == Py_None) {
66
throw std::runtime_error("None is not a valid input stream");
77
}
88
auto fileno = PyObject_GetAttrString(pyfile, "fileno");
9-
if (fileno == Py_None) {
9+
if (!fileno) { // NOT NONE!! NULL!!
1010
throw std::runtime_error("Passed object has no fileno() method");
1111
}
1212

@@ -20,5 +20,5 @@ buffer_pair from_pyobject(PyObject *pyfile)
2020
throw std::runtime_error("Failed to open input stream");
2121
}
2222

23-
return buffer_pair(new stdio_filebuf<char>(f), f);
23+
return new PyIStream(new stdio_filebuf<char>(f));
2424
}

libparse/py_iostream.h

Lines changed: 5 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,18 @@
22
#include "Python.h"
33
#include "stdio_filebuf.h"
44

5-
typedef std::pair<stdio_filebuf<char> *, FILE *> buffer_pair;
6-
// buffer_pair from_pyobject(PyObject *pyfile);
7-
8-
// struct PyIStream : public std::istream {
9-
// PyIStream(PyObject *pyfile) : buffers(from_pyobject(pyfile)), std::istream(std::get<0>(buffers)) {}
10-
11-
// ~PyIStream()
12-
// {
13-
// FILE *f;
14-
// stdio_filebuf<char> *buf;
15-
16-
// if ((f = std::get<1>(buffers))) {
17-
// fclose(f);
18-
// }
19-
// if ((buf = std::get<0>(buffers))) {
20-
// delete buf;
21-
// }
22-
// }
23-
24-
// private:
25-
// buffer_pair buffers;
26-
// };
27-
285
struct PyIStream : public std::istream {
29-
PyIStream(PyObject *pyfile)
30-
{
31-
if (pyfile == Py_None) {
32-
throw std::runtime_error("None is not a valid input stream");
33-
}
34-
auto fileno = PyObject_GetAttrString(pyfile, "fileno");
35-
if (!fileno) {
36-
throw std::runtime_error("Passed object has no fileno() method");
37-
}
38-
fd = PyObject_AsFileDescriptor(pyfile);
39-
if (fd == -1) {
40-
throw std::runtime_error("Failed to get file descriptor");
41-
}
42-
43-
f = fdopen(fd, "r");
44-
if (!f) {
45-
throw std::runtime_error("Failed to open input stream");
46-
}
6+
PyIStream(stdio_filebuf<char> *buffer) : std::istream(buffer), buffer(buffer) {}
477

48-
buf = new stdio_filebuf<char>(f);
49-
50-
init(buf);
51-
}
8+
static PyIStream *make_from(PyObject *pyfile);
529

5310
~PyIStream()
5411
{
55-
if (f) {
56-
fclose(f);
57-
}
58-
if (buf) {
59-
free(buf);
12+
if (buffer) {
13+
delete buffer;
6014
}
6115
}
6216

6317
private:
64-
int fd = -1;
65-
FILE *f = nullptr;
66-
stdio_filebuf<char> *buf = nullptr;
18+
stdio_filebuf<char> *buffer = nullptr;
6719
};

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
swig_opts=["-c++"],
3131
sources=[
3232
"libparse/libparse.cpp",
33+
"libparse/py_iostream.cpp",
3334
"libparse/libparse.i",
3435
],
3536
include_dirs=[

shell.nix

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
with pkgs; mkShell {
55
buildInputs = [
66
swig
7-
clang_16
8-
clang-tools_16
7+
clang_14
8+
clang-tools_14
99
python3Full
10-
valgrind
1110
twine
1211
];
12+
13+
CC = "clang";
14+
CXX = "clang++";
1315
}

0 commit comments

Comments
 (0)