Skip to content
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

the beginning of a painful migration #18

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ For more examples converting `data.frame`, `dgCMatrix`, `dgRMatrix`, `dgTMatrix`

This project uses Cython to provide bindings from C++ to Python.

```shell
cpptypes src/rds2py/lib --py src/rds2py/_cpphelpers.py --cpp src/rds2py/lib/bindings.cpp --dll _core
```

Steps to setup dependencies -

- git submodules is initialized in `extern/rds2cpp`
Expand Down
58 changes: 58 additions & 0 deletions bindings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* DO NOT MODIFY: this is automatically generated by the cpptypes */

#include <cstring>
#include <stdexcept>
#include <cstdint>

#ifdef _WIN32
#define PYAPI __declspec(dllexport)
#else
#define PYAPI
#endif

static char* copy_error_message(const char* original) {
auto n = std::strlen(original);
auto copy = new char[n + 1];
std::strcpy(copy, original);
return copy;
}

inline uintptr_t py_parser_extract_robject(uintptr_t);

inline uintptr_t py_parser_rds_file(std::string);

extern "C" {

PYAPI void free_error_message(char** msg) {
delete [] *msg;
}

PYAPI inline uintptr_t py_py_parser_extract_robject(uintptr_t ptr, int32_t* errcode, char** errmsg) {
inline uintptr_t output = 0;
try {
output = py_parser_extract_robject(ptr);
} catch(std::exception& e) {
*errcode = 1;
*errmsg = copy_error_message(e.what());
} catch(...) {
*errcode = 1;
*errmsg = copy_error_message("unknown C++ exception");
}
return output;
}

PYAPI inline uintptr_t py_py_parser_rds_file(std::string file, int32_t* errcode, char** errmsg) {
inline uintptr_t output = 0;
try {
output = py_parser_rds_file(file);
} catch(std::exception& e) {
*errcode = 1;
*errmsg = copy_error_message(e.what());
} catch(...) {
*errcode = 1;
*errmsg = copy_error_message("unknown C++ exception");
}
return output;
}

}
33 changes: 33 additions & 0 deletions bindings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# DO NOT MODIFY: this is automatically generated by the cpptypes

import os
import ctypes as ct


def _catch_errors(f):
def wrapper(*args):
errcode = ct.c_int32(0)
errmsg = ct.c_char_p(0)
output = f(*args, ct.byref(errcode), ct.byref(errmsg))
if errcode.value != 0:
msg = errmsg.value.decode("ascii")
lib.free_error_message(errmsg)
raise RuntimeError(msg)
return output

return wrapper


# TODO: surely there's a better way than whatever this is.
dirname = os.path.dirname(os.path.abspath(__file__))
contents = os.listdir(dirname)
lib = None
for x in contents:
if x.startswith("core") and not x.endswith("py"):
lib = ct.CDLL(os.path.join(dirname, x))
break

if lib is None:
raise ImportError("failed to find the core.* module")

lib.free_error_message.argtypes = [ct.POINTER(ct.c_char_p)]
38 changes: 17 additions & 21 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,30 @@
Learn more under: https://pyscaffold.org/
"""
import numpy
from Cython.Build import cythonize
from setuptools import setup
from setuptools.extension import Extension

if __name__ == "__main__":
try:
setup(
use_scm_version={"version_scheme": "no-guess-dev"},
ext_modules=cythonize(
[
Extension(
"rds2py.core",
["src/rds2py/lib/rds_parser.cpp", "src/rds2py/lib/parser.pyx"],
include_dirs=[
"extern/rds2cpp/include",
"extern/rds2cpp/_deps/byteme-src/include",
numpy.get_include(),
],
language="c++",
extra_compile_args=[
"-std=c++17",
],
extra_link_args=["-lz"],
)
],
compiler_directives={"language_level": "3"},
),
)
ext_modules=[
Extension(
"rds2py.core",
["src/rds2py/lib/rds_parser.cpp", "src/rds2py/lib/parser.pyx"],
include_dirs=[
"extern/rds2cpp/include",
"extern/rds2cpp/_deps/byteme-src/include",
numpy.get_include(),
],
language="c++",
extra_compile_args=[
"-std=c++17",
],
extra_link_args=["-lz"],
)
],
),
except: # noqa
print(
"\n\nAn error occurred while building the project, "
Expand Down
File renamed without changes.
42 changes: 42 additions & 0 deletions src/rds2py/_cpphelpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# DO NOT MODIFY: this is automatically generated by the cpptypes

import os
import ctypes as ct


def _catch_errors(f):
def wrapper(*args):
errcode = ct.c_int32(0)
errmsg = ct.c_char_p(0)
output = f(*args, ct.byref(errcode), ct.byref(errmsg))
if errcode.value != 0:
msg = errmsg.value.decode("ascii")
lib.free_error_message(errmsg)
raise RuntimeError(msg)
return output

return wrapper


# TODO: surely there's a better way than whatever this is.
dirname = os.path.dirname(os.path.abspath(__file__))
contents = os.listdir(dirname)
lib = None
for x in contents:
if x.startswith("_core") and not x.endswith("py"):
lib = ct.CDLL(os.path.join(dirname, x))
break

if lib is None:
raise ImportError("failed to find the _core.* module")

lib.free_error_message.argtypes = [ct.POINTER(ct.c_char_p)]

lib.py_py_parser_extract_robject.restype = ct.c_void_p
lib.py_py_parser_extract_robject.argtypes = [
ct.c_void_p,
ct.POINTER(ct.c_int32),
ct.POINTER(ct.c_char_p),
]

lib.py_py_parser_rds_file.restype = ct.c_void_p
58 changes: 58 additions & 0 deletions src/rds2py/lib/bindings.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/* DO NOT MODIFY: this is automatically generated by the cpptypes */

#include <cstring>
#include <stdexcept>
#include <cstdint>

#ifdef _WIN32
#define PYAPI __declspec(dllexport)
#else
#define PYAPI
#endif

static char* copy_error_message(const char* original) {
auto n = std::strlen(original);
auto copy = new char[n + 1];
std::strcpy(copy, original);
return copy;
}

uintptr_t py_parser_extract_robject(uintptr_t);

uintptr_t py_parser_rds_file(std::string);

extern "C" {

PYAPI void free_error_message(char** msg) {
delete [] *msg;
}

PYAPI uintptr_t py_py_parser_extract_robject(uintptr_t ptr, int32_t* errcode, char** errmsg) {
uintptr_t output = 0;
try {
output = py_parser_extract_robject(ptr);
} catch(std::exception& e) {
*errcode = 1;
*errmsg = copy_error_message(e.what());
} catch(...) {
*errcode = 1;
*errmsg = copy_error_message("unknown C++ exception");
}
return output;
}

PYAPI uintptr_t py_py_parser_rds_file(std::string file, int32_t* errcode, char** errmsg) {
uintptr_t output = 0;
try {
output = py_parser_rds_file(file);
} catch(std::exception& e) {
*errcode = 1;
*errmsg = copy_error_message(e.what());
} catch(...) {
*errcode = 1;
*errmsg = copy_error_message("unknown C++ exception");
}
return output;
}

}
Loading
Loading