File: shared.py

package info (click to toggle)
libnop 0.0~git20200728.45dfe0f-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,416 kB
  • sloc: cpp: 13,946; ansic: 3,537; makefile: 100; python: 73
file content (142 lines) | stat: -rw-r--r-- 4,512 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# Copyright 2018 The Native Object Protocols Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#
# Example of using libnop from python by wrapping operations in a shared
# library. The shared library is loaded using the ctypes module.
#

from ctypes import *
import sys
import os

# Define ctypes structures that mirror the basic protocol types.

# Three component vector of floats.
class Vec3(Structure):
  _fields_ = (('x', c_float), ('y', c_float), ('z', c_float))

  def __str__(self):
    return '(%.1f, %.1f, %.1f)' % (self.x, self.y, self.z)

# Triangle composed of three Vec3 structures.
class Triangle(Structure):
  _fields_ = (('a', Vec3), ('b', Vec3), ('c', Vec3))

  def __str__(self):
    return 'Triangle{%s, %s, %s}' % (self.a, self.b, self.c)

# Base Polyhedron structure. This carries the size of the Triangle array
# appended to the end of the structure.
class PolyhedronBase(Structure):
  _fields_ = (('size', c_size_t),)

# Builds a Polyhedron given either a list of Triangles or a capacity to reserve.
#
# This is equivalent to the following C header struct + dynamic array idiom:
#
# struct Polyhedron {
#   size_t size;
#   Triangle triangles[1];
# };
#
# Polyhedron* p = malloc(offsetof(Polyhedron, triangles) + reserve * sizeof(Triangle));
#
def Polyhedron(elements=[], reserve=None):
  if reserve is None:
    reserve = len(elements)

  # Triangle array of the required size.
  class ArrayType(Array):
    _type_ = Triangle
    _length_ = reserve

  # A subclass of PolyhedronBase with an array of Triangles appended.
  class PolyhedronType(PolyhedronBase):
    _fields_ = (('triangles', ArrayType),)

    def __str__(self):
      return 'Polyhedron{' + ', '.join(
        [str(self.triangles[i]) for i in range(self.size)]
      ) + '}'

  # Return an initialized instance of the Polyhedron.
  return PolyhedronType(reserve, ArrayType(*elements))

def LoadProtocolLibrary():
  global ProtocolLibrary
  global GetSerializedPolyhedron
  global SerializePolyhedron
  global DeserializePolyhedron

  # Load the shared library.
  ProtocolLibrary = cdll.LoadLibrary('out/shared_protocol.so')

  # Load the exported API and setup the function pointer types.
  GetSerializedPolyhedron = ProtocolLibrary.GetSerializedPolyhedron
  GetSerializedPolyhedron.argtypes = (c_void_p, c_size_t)
  GetSerializedPolyhedron.restype = c_ssize_t

  SerializePolyhedron = ProtocolLibrary.SerializePolyhedron
  SerializePolyhedron.argtypes = (POINTER(PolyhedronBase), c_void_p, c_size_t)
  SerializePolyhedron.restype = c_ssize_t

  DeserializePolyhedron = ProtocolLibrary.DeserializePolyhedron
  DeserializePolyhedron.argtypes = (POINTER(PolyhedronBase), c_void_p, c_size_t)
  DeserializePolyhedron.restype = c_ssize_t

def main():
  LoadProtocolLibrary()

  # Create a buffer to hold the serialized payload.
  payload_buffer = create_string_buffer(1024)

  # Create a Polyhedron and serialize it to the buffer.
  polyhedron = Polyhedron(
    (
      Triangle(Vec3(0, 0, 0), Vec3(1, 1, 1), Vec3(2, 2, 2)),
      Triangle(Vec3(3, 3, 3), Vec3(4, 4, 4), Vec3(5, 5, 5)),
      Triangle(Vec3(6, 6, 6), Vec3(7, 7, 7), Vec3(8, 8, 8))
    )
  )

  count = SerializePolyhedron(polyhedron, payload_buffer, len(payload_buffer))
  if count >= 0:
    print count, 'bytes:', payload_buffer[0:count].encode('hex')
  else:
    print 'Error:', -count

  # Create an empty Polyhedron that can hold up to 10 triangles read the payload.
  polyhedron = Polyhedron(reserve=10)

  count = DeserializePolyhedron(polyhedron, payload_buffer, len(payload_buffer))
  if count >= 0:
    print polyhedron
  else:
    print 'Error:', -count

  # Get a serialized Polyhedron from the library and then deserialize it.
  count = GetSerializedPolyhedron(payload_buffer, len(payload_buffer))
  if count < 0:
    print 'Error:', -count
    return;

  count = DeserializePolyhedron(polyhedron, payload_buffer, len(payload_buffer))
  if count >= 0:
    print polyhedron
  else:
    print 'Error:', -count

if __name__ == '__main__':
  main()