-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add init, del, repr, doc for pyType (#308)
* add init, del, repr, doc for pyType * add a export type test * minor fix on the test case * use 2 spaces rather than 4 spaces * use 2 spaces rather than 4 spaces * remove __del__ --------- Co-authored-by: Wei Xiang <[email protected]>
- Loading branch information
Showing
10 changed files
with
359 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,5 @@ tests/tbuiltinpyfromnim | |
*.pyc | ||
*.pyd | ||
*.so | ||
nimble.develop | ||
nimble.paths |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# begin Nimble config (version 2) | ||
when withDir(thisDir(), system.fileExists("nimble.paths")): | ||
include "nimble.paths" | ||
# end Nimble config |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
## Exporting Nim types as Python classes | ||
|
||
Warning! This is experimental. | ||
* An exported type should be a ref object and inherits `PyNimObjectExperimental` directly or indirectly. | ||
* The type will only be exported if at least one exported "method" is defined. | ||
* A proc will be exported as python type method *only* if it's first argument is of the corresponding type and is called `self`. If the first argument is not called `self`, the proc will exported as a global module function. | ||
* If you define functions that looks like initTestType or `$`, they will be exported as `__init__` and `__repr__` if the requirements are met. | ||
|
||
#### Simple Example | ||
```nim | ||
# mymodule.nim | ||
type TestType = ref object of PyNimObjectExperimental | ||
myField: string | ||
proc setMyField(self: TestType, value: string) {.exportpy.} = | ||
self.myField = value | ||
proc getMyField(self: TestType): string {.exportpy.} = | ||
self.myField | ||
``` | ||
|
||
``` py | ||
# test.py | ||
import mymodule | ||
tt = mymodule.TestType() | ||
tt.setMyField("Hello") | ||
assert(tt.getMyField() == "Hello") | ||
``` | ||
|
||
#### `__init__`, and `__repr__` | ||
* [example](../tests/export_pytype.nim) | ||
```nim | ||
# simple.nim | ||
## compile as simple.so | ||
import nimpy | ||
import strformat | ||
pyExportModule("simple") # only needed if your filename is not simple.nim | ||
type | ||
SimpleObj* = ref object of PyNimObjectExperimental | ||
a* : int | ||
## if | ||
## 1) the function name is like `init##TypeName` | ||
## 2) there is at least one argument | ||
## 3) the first argument name is "self" | ||
## 4) the first argument type is `##TypeName` | ||
## 5) there is no return type | ||
## we export this function as a python object method __init__ (tp_init in PyTypeObject) | ||
proc initSimpleObj*(self : SimpleObj, a : int = 1) {.exportpy} = | ||
echo "Calling initSimpleObj for SimpleObj" | ||
self.a = a | ||
## if | ||
## 1) the function name is like `$` | ||
## 2) there is only one argument | ||
## 3) the first argument name is "self" | ||
## 4) the first argument type is `##TypeName` | ||
## 5) the return type is `string` | ||
## we export this function as a python object method __repr__ (tp_repr in PyTypeObject) | ||
proc `$`*(self : SimpleObj): string {.exportpy.} = | ||
&"SimpleObj : a={self.a}" | ||
## Change doc string | ||
setModuleDocString("This is a test module") | ||
setDocStringForType(SimpleObj, "This is a test type") | ||
``` | ||
|
||
* Compile as `simple.so` | ||
```bash | ||
nim c --app:lib -o:./simple.so ./simple.nim | ||
``` | ||
|
||
* Use the exported python type in python | ||
```python | ||
import simple | ||
print(simple.__doc__) | ||
print(simple.SimpleObj.__doc__) | ||
obj = simple.SimpleObj(a = 2) | ||
print(obj) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
## Use nimpy to access numpy arrays from python | ||
|
||
* Get buffer from numpy array (PyObject) | ||
- Note | ||
- numpy will export buffer when the underlying memory block is C-Contiguous | ||
- if the underlying data is not C-Contiguous, there will be a PythonException thrown by numpy | ||
```nim | ||
proc asNimArray*[T](arr : PyObject, mode : int = PyBUF_READ) : ptr UncheckedArray[T] = | ||
var | ||
buf : RawPyBuffer | ||
getBuffer(arr, buf, mode.cint) | ||
``` | ||
|
||
* Shape and Strides | ||
```nim | ||
type | ||
NimNumpyArray*[T] = object | ||
originalPtr* : PyObject | ||
buf* : ptr UncheckedArray[T] | ||
shape* : seq[int] | ||
strides* : seq[int] | ||
c_contiguous* : bool | ||
f_contiguous* : bool | ||
proc asNimNumpyArray*[T](arr : PyObject, mode : int = PyBUF_READ) : NimNumpyArray[T] = | ||
#[ | ||
Function to translate numpy array into an object in Nim to represent the data for convinience. | ||
]# | ||
result.originalPtr = arr | ||
result.buf = asNimArray[T](arr, mode) | ||
result.shape = getAttr(arr, "shape").to(seq[int]) | ||
result.strides = getAttr(arr, "strides").to(seq[int]) | ||
result.c_contiguous = arr.flags["C_CONTIGUOUS"].to(bool) | ||
result.f_contiguous = arr.flags["F_CONTIGUOUS"].to(bool) | ||
proc accessNumpyMatrix*[T](matrix : NimNumpyArray[T], row, col : int): T = | ||
doAssert matrix.shape == 2 and matrix.strides == 2 | ||
return matrix.buf[ | ||
row * matrix.strides[0] + col * matrix.strides[1] | ||
] | ||
``` | ||
|
||
* ArrayMancer Tensor | ||
- Given the exposed buffer, you can use cpuStorageFromBuffer from ArrayMancer Tensor wihout making a copy |
Oops, something went wrong.