https://github.com/shigekikarita/mir-pybuffer
buffer protocol interface for Python and D
https://github.com/shigekikarita/mir-pybuffer
buffer-protocol dlang mir numpy python3
Last synced: about 1 year ago
JSON representation
buffer protocol interface for Python and D
- Host: GitHub
- URL: https://github.com/shigekikarita/mir-pybuffer
- Owner: ShigekiKarita
- License: bsl-1.0
- Created: 2018-04-02T11:51:12.000Z (about 8 years ago)
- Default Branch: master
- Last Pushed: 2018-11-14T16:27:00.000Z (over 7 years ago)
- Last Synced: 2025-04-13T12:12:22.581Z (about 1 year ago)
- Topics: buffer-protocol, dlang, mir, numpy, python3
- Language: Python
- Homepage:
- Size: 318 KB
- Stars: 9
- Watchers: 3
- Forks: 0
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# [WARNING]
**this repository is outdated. moved to [mir-pybind](https://github.com/ShigekiKarita/mir-pybind)**
# mir-pybuffer
[](https://travis-ci.org/ShigekiKarita/mir-pybuffer)
[](https://pypi.org/project/pybuffer)
[](https://code.dlang.org/packages/mir-pybuffer)
mir-pybuffer provides simpler communication interface between C/D-language and python ndarrays (e.g., numpy, PIL) in [Buffer Protocol](https://docs.python.org/3/c-api/buffer.html#buffer-protocol).
## installation
``` console
$ pip install pybuffer
$ dub fetch mir-pybuffer # for D (mir) extention
```
for C extention, you do not need anything but `Python.h`.
you can see a read/write example in [c-bp.c](c-bp.c) and run it by `$ make test-c`.
## usage
### python side
All you need to do is calling C/D dynamic library with `pybuffer.CDLL`.
``` python
import ctypes
import numpy
import pybuffer
# ndarrays
x = numpy.array([[0, 1, 2], [3, 4, 5]]).astype(numpy.float64)
y = numpy.array([0, 1, 2]).astype(numpy.float64)
# load dynamic library written in d or c
lib = pybuffer.CDLL("./libyour-dub-lib.so")
err = lib.func1(x, y, ctypes.c_double(2.0))
assert err == 0
```
### D side
currently mir-pybuffer only supports ndslice functions that return void.
To create dynamic library, you also need to add `"targetType": "dynamicLibrary"` in [dub.json](test/dub.json).
``` d
import mir.ndslice : Slice, Contiguous;
// NOTE: DO NOT import pybuffer without ": pybuffer, MixinPyBufferWrappers"
// because it fails to generate wrappers.
import pybuffer : pybuffer, MixinPyBufferWrappers;
@pybuffer
void func1(Slice!(double*, 2) mat, Slice!(double*, 1) vec, double a) {
mat[0][] += vec;
vec[] *= a;
}
mixin MixinPyBufferWrappers;
```
run this example by `$ make test-mir`.
## detail
`@pybuffer` and `mixin MixinPyBufferWrappers;` will generate wrapper functions as follows:
``` d
pragma(mangle, __traits(identifier, pybuffer_func1))
extern(C) auto pybuffer_func1( ref Py_buffer a0 , ref Py_buffer a1 , double a2 ) {
import mir.ndslice.connect.cpython;
import std.stdio : writeln;
Slice!(double*, 2) _a0;
{
auto err = fromPythonBuffer( _a0 , a0 );
if (err != PythonBufferErrorCode.success) { writeln(err); return err; }
}
Slice!(double*, 1) _a1;
{
auto err = fromPythonBuffer( _a1 , a1 );
if (err != PythonBufferErrorCode.success) { writeln(err); return err; }
}
func1( _a0 , _a1 , a2 );
return PythonBufferErrorCode.success;
}
```
you can see the actual generated codes by `lib.print_generated()` in python.
`pybuffer.CDLL` calls `pybuffer_func1` instead of `func1` with PyBuffer arguments and error code handling.
see [mir.ndslice.connect.cpython.PythonBufferErrorCode](http://docs.algorithm.dlang.io/latest/mir_ndslice_connect_cpython.html#.PythonBufferErrorCode) for error code definitions.
## known issues
- `import pybuffer` without ` : pybuffer, MixinPyBufferWrappers` causes a empty generated string.