pybind 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +25 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +132 -0
- data/Rakefile +5 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/examples/autocall_functions.rb +15 -0
- data/examples/hello_world.py +1 -0
- data/examples/hello_world.rb +14 -0
- data/examples/mnist.softmax.rb +53 -0
- data/examples/numpy.rb +9 -0
- data/lib/pybind.rb +14 -0
- data/lib/pybind/autocall.rb +14 -0
- data/lib/pybind/core_ext/basic.rb +66 -0
- data/lib/pybind/error.rb +38 -0
- data/lib/pybind/import.rb +51 -0
- data/lib/pybind/init.rb +23 -0
- data/lib/pybind/libpython.rb +371 -0
- data/lib/pybind/python/investigator.py +10 -0
- data/lib/pybind/struct.rb +36 -0
- data/lib/pybind/typecast.rb +28 -0
- data/lib/pybind/types.rb +21 -0
- data/lib/pybind/types/basic.rb +70 -0
- data/lib/pybind/types/dict.rb +94 -0
- data/lib/pybind/types/function.rb +26 -0
- data/lib/pybind/types/list.rb +39 -0
- data/lib/pybind/types/object.rb +9 -0
- data/lib/pybind/types/sequence.rb +26 -0
- data/lib/pybind/types/set.rb +19 -0
- data/lib/pybind/types/slice.rb +19 -0
- data/lib/pybind/types/tuple.rb +45 -0
- data/lib/pybind/utils.rb +81 -0
- data/lib/pybind/version.rb +3 -0
- data/lib/pybind/wrapper.rb +120 -0
- data/lib/pybind/wrapper/attr_accessor.rb +53 -0
- data/lib/pybind/wrapper/operator.rb +82 -0
- data/lib/pybind/wrapper/rich_comparer.rb +39 -0
- data/pybind.gemspec +40 -0
- metadata +157 -0
@@ -0,0 +1,10 @@
|
|
1
|
+
from distutils.sysconfig import get_config_var
|
2
|
+
import sys
|
3
|
+
|
4
|
+
print('EXECUTABLE: ' + str(sys.executable))
|
5
|
+
print('EXECPREFIX: ' + str(sys.exec_prefix))
|
6
|
+
print('PREFIX: ' + str(sys.prefix))
|
7
|
+
if sys.version_info >= (3, 3):
|
8
|
+
print('IMPLEMENTATIONMULTIARCH: ' + str(sys.implementation._multiarch))
|
9
|
+
for var in ('VERSION', 'INSTSONAME', 'LIBRARY', 'LDLIBRARY', 'LIBDIR', 'PYTHONFRAMEWORKPREFIX', 'MULTIARCH'):
|
10
|
+
print(var + ': ' + str(get_config_var(var)))
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module PyBind
|
4
|
+
class PyObjectStruct < FFI::Struct
|
5
|
+
layout ob_refcnt: :ssize_t,
|
6
|
+
ob_type: PyObjectStruct.by_ref
|
7
|
+
|
8
|
+
def self.null
|
9
|
+
new(FFI::Pointer::NULL)
|
10
|
+
end
|
11
|
+
|
12
|
+
def none?
|
13
|
+
PyBind.None.to_ptr == to_ptr
|
14
|
+
end
|
15
|
+
|
16
|
+
def kind_of?(klass)
|
17
|
+
case klass
|
18
|
+
when PyBind::PyObjectStruct
|
19
|
+
value = LibPython.PyObject_IsInstance(self, klass)
|
20
|
+
raise PyError.fetch if value == -1
|
21
|
+
value == 1
|
22
|
+
else
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_ruby_object
|
28
|
+
PyObject.new(self)
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_python_struct
|
32
|
+
self
|
33
|
+
end
|
34
|
+
alias_method :to_python, :to_python_struct
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PyBind
|
2
|
+
module TypeCast
|
3
|
+
def self.from_python(pyobj)
|
4
|
+
pystruct = pyobj.to_python_struct
|
5
|
+
return nil if pystruct.null? || pystruct.none?
|
6
|
+
|
7
|
+
Types.pytypes.each do |pytype|
|
8
|
+
return pytype.from_python(pystruct) if pytype.python_instance?(pystruct)
|
9
|
+
end
|
10
|
+
PyObject.from_python(pystruct)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.to_python_arguments(indices)
|
14
|
+
if indices.length == 1
|
15
|
+
indices = indices[0]
|
16
|
+
else
|
17
|
+
indices = PyTuple.new(indices)
|
18
|
+
end
|
19
|
+
indices.to_python
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class PyObjectStruct
|
24
|
+
def to_ruby
|
25
|
+
TypeCast.from_python(self)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/pybind/types.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
module PyBind
|
2
|
+
module Types
|
3
|
+
class << self
|
4
|
+
attr_reader :pytypes
|
5
|
+
end
|
6
|
+
|
7
|
+
@pytypes ||= []
|
8
|
+
def self.register_type(pytype)
|
9
|
+
@pytypes.unshift(pytype)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'pybind/core_ext/basic'
|
15
|
+
require 'pybind/types/basic'
|
16
|
+
require 'pybind/types/object'
|
17
|
+
require 'pybind/types/tuple'
|
18
|
+
require 'pybind/types/slice'
|
19
|
+
require 'pybind/types/list'
|
20
|
+
require 'pybind/types/dict'
|
21
|
+
require 'pybind/types/set'
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PyType
|
3
|
+
include PyObjectWrapper
|
4
|
+
pybind_type LibPython.PyType_Type
|
5
|
+
|
6
|
+
def to_s
|
7
|
+
return super unless has_attribute?('__name__')
|
8
|
+
get_attribute('__name__')
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class PyString
|
13
|
+
include PyObjectWrapper
|
14
|
+
|
15
|
+
pybind_type LibPython.PyString_Type do |pystruct|
|
16
|
+
FFI::MemoryPointer.new(:string) do |str_ptr|
|
17
|
+
FFI::MemoryPointer.new(:int) do |len_ptr|
|
18
|
+
res = LibPython.PyString_AsStringAndSize(pystruct, str_ptr, len_ptr)
|
19
|
+
return nil if res == -1 # FIXME: error
|
20
|
+
|
21
|
+
len = len_ptr.get(:int, 0)
|
22
|
+
return str_ptr.get_pointer(0).read_string(len)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class PyUnicode
|
29
|
+
include PyObjectWrapper
|
30
|
+
|
31
|
+
pybind_type LibPython.PyUnicode_Type do |pystruct|
|
32
|
+
pystruct = LibPython.PyUnicode_AsUTF8String(pystruct)
|
33
|
+
PyString.from_python(pystruct).force_encoding(Encoding::UTF_8)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class PyInt
|
38
|
+
include PyObjectWrapper
|
39
|
+
|
40
|
+
pybind_type LibPython.PyInt_Type do |pystruct|
|
41
|
+
LibPython.PyInt_AsSsize_t(pystruct)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class PyBool
|
46
|
+
include PyObjectWrapper
|
47
|
+
|
48
|
+
pybind_type LibPython.PyBool_Type do |pystruct|
|
49
|
+
LibPython.PyInt_AsSsize_t(pystruct) != 0
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class PyFloat
|
54
|
+
include PyObjectWrapper
|
55
|
+
|
56
|
+
pybind_type LibPython.PyFloat_Type do |pystruct|
|
57
|
+
LibPython.PyFloat_AsDouble(pystruct)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class PyComplex
|
62
|
+
include PyObjectWrapper
|
63
|
+
|
64
|
+
pybind_type LibPython.PyComplex_Type do |pystruct|
|
65
|
+
real = LibPython.PyComplex_RealAsDouble(pystruct)
|
66
|
+
imag = LibPython.PyComplex_ImagAsDouble(pystruct)
|
67
|
+
Complex(real, imag)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PyDict
|
3
|
+
include Enumerable
|
4
|
+
include PyObjectWrapper
|
5
|
+
pybind_type LibPython.PyDict_Type
|
6
|
+
|
7
|
+
def self.new(init = nil)
|
8
|
+
case init
|
9
|
+
when PyObjectStruct
|
10
|
+
super
|
11
|
+
when nil
|
12
|
+
new(LibPython.PyDict_New())
|
13
|
+
when Hash
|
14
|
+
new.tap do |dict|
|
15
|
+
init.each do |key, value|
|
16
|
+
dict[key] = value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
else
|
20
|
+
raise TypeError, "the argument must be a PyObjectStruct or a Hash"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](key)
|
25
|
+
case key
|
26
|
+
when String, Symbol
|
27
|
+
LibPython.PyDict_GetItemString(@pystruct, key.to_s).to_ruby
|
28
|
+
else
|
29
|
+
key = key.to_python
|
30
|
+
LibPython.PyDict_GetItem(@pystruct, key).to_ruby
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def []=(key, value)
|
35
|
+
value = value.to_python
|
36
|
+
case key
|
37
|
+
when String, Symbol
|
38
|
+
LibPython.PyDict_SetItemString(@pystruct, key.to_s, value)
|
39
|
+
else
|
40
|
+
key = key.to_python
|
41
|
+
LibPython.PyDict_SetItem(@pystruct, key, value)
|
42
|
+
end
|
43
|
+
value
|
44
|
+
end
|
45
|
+
|
46
|
+
def delete(key)
|
47
|
+
case key
|
48
|
+
when String, Symbol
|
49
|
+
value = LibPython.PyDict_GetItemString(@pystruct, key).to_ruby
|
50
|
+
LibPython.PyDict_DelItemString(@pystruct, key.to_s)
|
51
|
+
else
|
52
|
+
key = key.to_python
|
53
|
+
value = LibPython.PyDict_GetItem(@pystruct, key).to_ruby
|
54
|
+
LibPython.PyDict_DelItem(@pystruct, key)
|
55
|
+
end
|
56
|
+
value
|
57
|
+
end
|
58
|
+
|
59
|
+
def size
|
60
|
+
LibPython.PyDict_Size(@pystruct)
|
61
|
+
end
|
62
|
+
|
63
|
+
def keys
|
64
|
+
LibPython.PyDict_Keys(@pystruct).to_ruby
|
65
|
+
end
|
66
|
+
|
67
|
+
def values
|
68
|
+
LibPython.PyDict_Values(@pystruct).to_ruby
|
69
|
+
end
|
70
|
+
|
71
|
+
def has_key?(key)
|
72
|
+
key = key.to_python
|
73
|
+
value = LibPython.PyDict_Contains(@pystruct, key)
|
74
|
+
raise PyError.fetch if value == -1
|
75
|
+
value == 1
|
76
|
+
end
|
77
|
+
|
78
|
+
def to_a
|
79
|
+
LibPython.PyDict_Items(@pystruct).to_ruby
|
80
|
+
end
|
81
|
+
|
82
|
+
def to_hash
|
83
|
+
Hash[to_a]
|
84
|
+
end
|
85
|
+
|
86
|
+
def each
|
87
|
+
return enum_for unless block_given?
|
88
|
+
keys.each do |key|
|
89
|
+
yield key, self[key]
|
90
|
+
end
|
91
|
+
self
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PyBind
|
2
|
+
module PyCallable
|
3
|
+
end
|
4
|
+
|
5
|
+
class PyFunction
|
6
|
+
include PyCallable
|
7
|
+
include PyObjectWrapper
|
8
|
+
pybind_type PyBind.types.FunctionType
|
9
|
+
end
|
10
|
+
|
11
|
+
class PyMethod
|
12
|
+
include PyCallable
|
13
|
+
include PyObjectWrapper
|
14
|
+
pybind_type PyBind.types.MethodType
|
15
|
+
end
|
16
|
+
|
17
|
+
class PyBuiltinFunction
|
18
|
+
include PyCallable
|
19
|
+
include PyObjectWrapper
|
20
|
+
pybind_type PyBind.types.BuiltinFunctionType
|
21
|
+
end
|
22
|
+
|
23
|
+
class PyType
|
24
|
+
include PyCallable
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pybind/types/sequence'
|
2
|
+
|
3
|
+
module PyBind
|
4
|
+
class PyList
|
5
|
+
include PyObjectWrapper
|
6
|
+
pybind_type LibPython.PyList_Type
|
7
|
+
|
8
|
+
include PySequence
|
9
|
+
|
10
|
+
def self.new(init = nil)
|
11
|
+
case init
|
12
|
+
when PyObjectStruct
|
13
|
+
super
|
14
|
+
when nil
|
15
|
+
new(0)
|
16
|
+
when Integer
|
17
|
+
new(LibPython.PyList_New(init))
|
18
|
+
when Array
|
19
|
+
new.tap do |list|
|
20
|
+
init.each do |item|
|
21
|
+
list << item
|
22
|
+
end
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise TypeError, "the argument must be an Integer, a PyObjectStruct or a Array"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def <<(value)
|
30
|
+
value = value.to_python
|
31
|
+
LibPython.PyList_Append(@pystruct, value)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def size
|
36
|
+
LibPython.PyList_Size(@pystruct)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PyBind
|
2
|
+
module PySequence
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def include?(value)
|
6
|
+
value = value.to_python
|
7
|
+
value = LibPython.PySequence_Contains(@pystruct, value)
|
8
|
+
raise PyError.fetch if value == -1
|
9
|
+
value == 1
|
10
|
+
end
|
11
|
+
|
12
|
+
def each
|
13
|
+
return enum_for unless block_given?
|
14
|
+
size.times do |i|
|
15
|
+
yield self[i]
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_a
|
21
|
+
each.to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
alias_method :to_ary, :to_a
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PySet
|
3
|
+
include PyObjectWrapper
|
4
|
+
pybind_type LibPython.PySet_Type
|
5
|
+
|
6
|
+
def initialize(init)
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
def size
|
11
|
+
LibPython.PySet_Size(@pystruct)
|
12
|
+
end
|
13
|
+
|
14
|
+
def include?(obj)
|
15
|
+
obj = obj.to_python
|
16
|
+
LibPython.PySet_Contains(@pystruct, obj) == 1
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module PyBind
|
2
|
+
class PySlice
|
3
|
+
include PyObjectWrapper
|
4
|
+
pybind_type LibPython.PySlice_Type
|
5
|
+
|
6
|
+
def self.new(start, stop = nil, step = nil)
|
7
|
+
if stop.nil? && step.nil?
|
8
|
+
start, stop = nil, start
|
9
|
+
return super(stop) if stop.kind_of?(PyObjectStruct)
|
10
|
+
end
|
11
|
+
start = start ? start.to_python : PyObjectStruct.null
|
12
|
+
stop = stop ? stop.to_python : PyObjectStruct.null
|
13
|
+
step = step ? step.to_python : PyObjectStruct.null
|
14
|
+
pyobj = LibPython.PySlice_New(start, stop, step)
|
15
|
+
raise PyError.fetch if pyobj.null?
|
16
|
+
pyobj.to_ruby
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'pybind/types/sequence'
|
2
|
+
|
3
|
+
module PyBind
|
4
|
+
class PyTuple
|
5
|
+
include PyObjectWrapper
|
6
|
+
pybind_type LibPython.PyTuple_Type
|
7
|
+
|
8
|
+
include PySequence
|
9
|
+
|
10
|
+
def self.new(init)
|
11
|
+
case init
|
12
|
+
when PyObjectStruct
|
13
|
+
super
|
14
|
+
when Integer
|
15
|
+
super(LibPython.PyTuple_New(init))
|
16
|
+
when Array
|
17
|
+
tuple = new(init.size)
|
18
|
+
init.each_with_index do |obj, index|
|
19
|
+
tuple[index] = obj
|
20
|
+
end
|
21
|
+
tuple
|
22
|
+
else
|
23
|
+
raise TypeError, "the argument must be an Integer, a PyObjectStruct or a Array"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Make tuple from array
|
28
|
+
def self.[](*ary)
|
29
|
+
new(ary)
|
30
|
+
end
|
31
|
+
|
32
|
+
def size
|
33
|
+
LibPython.PyTuple_Size(@pystruct)
|
34
|
+
end
|
35
|
+
|
36
|
+
def [](index)
|
37
|
+
LibPython.PyTuple_GetItem(@pystruct, index).to_ruby
|
38
|
+
end
|
39
|
+
|
40
|
+
def []=(index, value)
|
41
|
+
value = value.to_python
|
42
|
+
LibPython.PyTuple_SetItem(@pystruct, index, value)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|