From 8760d74ddaa377e6d715416cf62c19fb4641a90f Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Tue, 6 May 2025 17:23:48 +0100 Subject: [PATCH 01/20] Testing json.dumps --- sample_apps/advanced_example_py/advanced_example1.py | 7 +++++++ sample_apps/advanced_example_py/advanced_example2.py | 7 +++++++ sample_apps/first_example_py/first_example.py | 7 +++++++ 3 files changed, 21 insertions(+) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index 98f7eb94..ad82775d 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -49,6 +49,13 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents + output = { + "dummy": 0, + "timestamp": 0, + "data_entry": type(data_entry), + } + print(f"Testing json.dumps: {json.dumps(output, indent=2)}") + if stream_idx == GENERATOR_OUT_STREAM_IDX: # Extract data from the received entry data = ctypes.cast(data_entry.data, ctypes.POINTER(example_msg)).contents diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index b34c4916..3bae32b2 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -47,6 +47,13 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents + output = { + "dummy": 0, + "timestamp": 0, + "data_entry": type(data_entry), + } + print(f"Testing json.dumps: {json.dumps(output, indent=2)}") + if stream_idx == GENERATOR_PB_OUT_STREAM_IDX: state.received_counter += 1 diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index 978d6a66..07987112 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -47,6 +47,13 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents + output = { + "dummy": 0, + "timestamp": 0, + "data_entry": type(data_entry), + } + print(f"Testing json.dumps: {json.dumps(output, indent=2)}") + if stream_idx == GENERATOR_OUT_STREAM_IDX: state.received_counter += 1 From 07a5114b30610eaa5eaf04ca7bddb881270a3631 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Tue, 6 May 2025 17:56:49 +0100 Subject: [PATCH 02/20] Add json --- sample_apps/advanced_example_py/advanced_example1.py | 2 +- sample_apps/advanced_example_py/advanced_example2.py | 2 +- sample_apps/first_example_py/first_example.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index ad82775d..e1b0395c 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -1,6 +1,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. - +import json import os import sys import ctypes diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index 3bae32b2..19956229 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -1,6 +1,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. - +import json import os import sys import ctypes diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index 07987112..a4dddf07 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -1,6 +1,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. - +import json import os import sys import ctypes From a2845d30651e6850fa52a69f4a4faf1e6540a23d Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Tue, 6 May 2025 18:34:21 +0100 Subject: [PATCH 03/20] Fix --- sample_apps/advanced_example_py/advanced_example1.py | 2 +- sample_apps/advanced_example_py/advanced_example2.py | 2 +- sample_apps/first_example_py/first_example.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index e1b0395c..8a52dce1 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -52,7 +52,7 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s output = { "dummy": 0, "timestamp": 0, - "data_entry": type(data_entry), + "stream_idx": stream_idx, } print(f"Testing json.dumps: {json.dumps(output, indent=2)}") diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index 19956229..92e712b3 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -50,7 +50,7 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s output = { "dummy": 0, "timestamp": 0, - "data_entry": type(data_entry), + "stream_idx": stream_idx, } print(f"Testing json.dumps: {json.dumps(output, indent=2)}") diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index a4dddf07..1d7d9b4d 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -50,7 +50,7 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s output = { "dummy": 0, "timestamp": 0, - "data_entry": type(data_entry), + "stream_idx": stream_idx, } print(f"Testing json.dumps: {json.dumps(output, indent=2)}") From 44ef15512f5c73c95e67207c73cc54a55024af08 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Tue, 6 May 2025 21:17:55 +0100 Subject: [PATCH 04/20] Test --- sample_apps/advanced_example_py/advanced_example1.py | 5 +++++ sample_apps/advanced_example_py/advanced_example2.py | 5 +++++ sample_apps/first_example_py/first_example.py | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index 8a52dce1..86348975 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -54,6 +54,11 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s "timestamp": 0, "stream_idx": stream_idx, } + print("BEFORE") + a = 10000 * [0] + for i in range(10000): + a[i] = 100 * [1] + print("AFTER") print(f"Testing json.dumps: {json.dumps(output, indent=2)}") if stream_idx == GENERATOR_OUT_STREAM_IDX: diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index 92e712b3..ec98bf89 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -52,6 +52,11 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s "timestamp": 0, "stream_idx": stream_idx, } + print("BEFORE") + a = 10000 * [0] + for i in range(10000): + a[i] = 100 * [1] + print("AFTER") print(f"Testing json.dumps: {json.dumps(output, indent=2)}") if stream_idx == GENERATOR_PB_OUT_STREAM_IDX: diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index 1d7d9b4d..b7980781 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -52,6 +52,11 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s "timestamp": 0, "stream_idx": stream_idx, } + print("BEFORE") + a = 10000 * [0] + for i in range(10000): + a[i] = 100 * [1] + print("AFTER") print(f"Testing json.dumps: {json.dumps(output, indent=2)}") if stream_idx == GENERATOR_OUT_STREAM_IDX: From e55ee13fd9ecc9853e35bca610346b32c612e1d0 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Wed, 7 May 2025 09:51:29 +0100 Subject: [PATCH 05/20] Check if it is PYTHONMALLOC --- setup_jrtc_env.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/setup_jrtc_env.sh b/setup_jrtc_env.sh index dad2d40b..a635cd3c 100755 --- a/setup_jrtc_env.sh +++ b/setup_jrtc_env.sh @@ -2,6 +2,7 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. +export PYTHONMALLOC=malloc export JRTC_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" export JRTC_OUT_DIR=$JRTC_PATH/out export JRTC_APP_PATH=$JRTC_OUT_DIR/lib/ From 1bbe6dbfb0c6d8132b4ccb028d95429fe9c3bb70 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 12:29:51 +0100 Subject: [PATCH 06/20] Fix --- sample_apps/first_example_py/first_example.py | 3 +- .../data_generator/generated_data.py | 882 ++++++++++++++ .../generated_data_pb.py | 1012 +++++++++++++++++ .../simple_input/simple_input.py | 882 ++++++++++++++ .../simple_input_protobuf/simple_input_pb.py | 1012 +++++++++++++++++ src/wrapper_apis/python/jrtc_app.py | 334 ++++-- .../python/jrtc_router_stream_id.py | 4 +- 7 files changed, 4004 insertions(+), 125 deletions(-) create mode 100644 sample_apps/jbpf_codelets/data_generator/generated_data.py create mode 100644 sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py create mode 100644 sample_apps/jbpf_codelets/simple_input/simple_input.py create mode 100644 sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index b7980781..a0f1b1f4 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -22,7 +22,7 @@ # Define the state variables for the application class AppStateVars(ctypes.Structure): _fields_ = [ - ("app", ctypes.POINTER(JrtcApp)), + ("app", ctypes.py_object), # add custom fields below ("agg_cnt", ctypes.c_int), @@ -128,6 +128,7 @@ def jrtc_start_app(capsule): state.app = jrtc_app_create(capsule, app_cfg, app_handler, state) # run the app - This is blocking until the app exists + print(f"type(state.app) = {type(state.app)}") jrtc_app_run(state.app) # clean up app resources diff --git a/sample_apps/jbpf_codelets/data_generator/generated_data.py b/sample_apps/jbpf_codelets/data_generator/generated_data.py new file mode 100644 index 00000000..6b016f84 --- /dev/null +++ b/sample_apps/jbpf_codelets/data_generator/generated_data.py @@ -0,0 +1,882 @@ +r"""Wrapper for generated_data.h + +Generated with: +/usr/local/bin/ctypesgen generated_data.h -o generated_data.py + +Do not modify this file. +""" + +__docformat__ = "restructuredtext" + +# Begin preamble for Python + +import ctypes +import sys +from ctypes import * # noqa: F401, F403 + +_int_types = (ctypes.c_int16, ctypes.c_int32) +if hasattr(ctypes, "c_int64"): + # Some builds of ctypes apparently do not have ctypes.c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (ctypes.c_int64,) +for t in _int_types: + if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): + c_ptrdiff_t = t +del t +del _int_types + + + +class UserString: + def __init__(self, seq): + if isinstance(seq, bytes): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq).encode() + + def __bytes__(self): + return self.data + + def __str__(self): + return self.data.decode() + + def __repr__(self): + return repr(self.data) + + def __int__(self): + return int(self.data.decode()) + + def __long__(self): + return int(self.data.decode()) + + def __float__(self): + return float(self.data.decode()) + + def __complex__(self): + return complex(self.data.decode()) + + def __hash__(self): + return hash(self.data) + + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + else: + return self.data <= string + + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + else: + return self.data < string + + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + else: + return self.data >= string + + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + else: + return self.data > string + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + else: + return self.data == string + + def __ne__(self, string): + if isinstance(string, UserString): + return self.data != string.data + else: + return self.data != string + + def __contains__(self, char): + return char in self.data + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + return self.__class__(self.data[index]) + + def __getslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, bytes): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other).encode()) + + def __radd__(self, other): + if isinstance(other, bytes): + return self.__class__(other + self.data) + else: + return self.__class__(str(other).encode() + self.data) + + def __mul__(self, n): + return self.__class__(self.data * n) + + __rmul__ = __mul__ + + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): + return self.__class__(self.data.capitalize()) + + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + + def count(self, sub, start=0, end=sys.maxsize): + return self.data.count(sub, start, end) + + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + + def endswith(self, suffix, start=0, end=sys.maxsize): + return self.data.endswith(suffix, start, end) + + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + + def find(self, sub, start=0, end=sys.maxsize): + return self.data.find(sub, start, end) + + def index(self, sub, start=0, end=sys.maxsize): + return self.data.index(sub, start, end) + + def isalpha(self): + return self.data.isalpha() + + def isalnum(self): + return self.data.isalnum() + + def isdecimal(self): + return self.data.isdecimal() + + def isdigit(self): + return self.data.isdigit() + + def islower(self): + return self.data.islower() + + def isnumeric(self): + return self.data.isnumeric() + + def isspace(self): + return self.data.isspace() + + def istitle(self): + return self.data.istitle() + + def isupper(self): + return self.data.isupper() + + def join(self, seq): + return self.data.join(seq) + + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + + def lower(self): + return self.__class__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__class__(self.data.lstrip(chars)) + + def partition(self, sep): + return self.data.partition(sep) + + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + + def rfind(self, sub, start=0, end=sys.maxsize): + return self.data.rfind(sub, start, end) + + def rindex(self, sub, start=0, end=sys.maxsize): + return self.data.rindex(sub, start, end) + + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return self.data.rpartition(sep) + + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + + def splitlines(self, keepends=0): + return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): + return self.data.startswith(prefix, start, end) + + def strip(self, chars=None): + return self.__class__(self.data.strip(chars)) + + def swapcase(self): + return self.__class__(self.data.swapcase()) + + def title(self): + return self.__class__(self.data.title()) + + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + + def upper(self): + return self.__class__(self.data.upper()) + + def zfill(self, width): + return self.__class__(self.data.zfill(width)) + + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + + def __init__(self, string=""): + self.data = string + + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + sub + self.data[index + 1 :] + + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + self.data[index + 1 :] + + def __setslice__(self, start, end, sub): + start = max(start, 0) + end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start] + sub.data + self.data[end:] + elif isinstance(sub, bytes): + self.data = self.data[:start] + sub + self.data[end:] + else: + self.data = self.data[:start] + str(sub).encode() + self.data[end:] + + def __delslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + + def immutable(self): + return UserString(self.data) + + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, bytes): + self.data += other + else: + self.data += str(other).encode() + return self + + def __imul__(self, n): + self.data *= n + return self + + +class String(MutableString, ctypes.Union): + + _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] + + def __init__(self, obj=b""): + if isinstance(obj, (bytes, UserString)): + self.data = bytes(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(ctypes.POINTER(ctypes.c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from bytes + elif isinstance(obj, bytes): + return cls(obj) + + # Convert from str + elif isinstance(obj, str): + return cls(obj.encode()) + + # Convert from c_char_p + elif isinstance(obj, ctypes.c_char_p): + return obj + + # Convert from POINTER(ctypes.c_char) + elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) + + # Convert from ctypes.c_char array + elif isinstance(obj, ctypes.c_char * len(obj)): + return obj + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + + from_param = classmethod(from_param) + + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to ctypes.c_void_p. +def UNCHECKED(type): + if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": + return type + else: + return ctypes.c_void_p + + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self, func, restype, argtypes, errcheck): + self.func = func + self.func.restype = restype + self.argtypes = argtypes + if errcheck: + self.func.errcheck = errcheck + + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.func(*fixed_args + list(args[i:])) + + +def ord_if_char(value): + """ + Simple helper used for casts to simple builtin types: if the argument is a + string type, it will be converted to it's ordinal value. + + This function will raise an exception if the argument is string with more + than one characters. + """ + return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value + +# End preamble + +_libs = {} +_libdirs = [] + +# Begin loader + +""" +Load libraries - appropriately for all our supported platforms +""" +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import ctypes +import ctypes.util +import glob +import os.path +import platform +import re +import sys + + +def _environ_path(name): + """Split an environment variable into a path-like list elements""" + if name in os.environ: + return os.environ[name].split(":") + return [] + + +class LibraryLoader: + """ + A base class For loading of libraries ;-) + Subclasses load libraries for specific platforms. + """ + + # library names formatted specifically for platforms + name_formats = ["%s"] + + class Lookup: + """Looking up calling conventions for a platform""" + + mode = ctypes.DEFAULT_MODE + + def __init__(self, path): + super(LibraryLoader.Lookup, self).__init__() + self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) + + def get(self, name, calling_convention="cdecl"): + """Return the given name according to the selected calling convention""" + if calling_convention not in self.access: + raise LookupError( + "Unknown calling convention '{}' for function '{}'".format( + calling_convention, name + ) + ) + return getattr(self.access[calling_convention], name) + + def has(self, name, calling_convention="cdecl"): + """Return True if this given calling convention finds the given 'name'""" + if calling_convention not in self.access: + return False + return hasattr(self.access[calling_convention], name) + + def __getattr__(self, name): + return getattr(self.access["cdecl"], name) + + def __init__(self): + self.other_dirs = [] + + def __call__(self, libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + # noinspection PyBroadException + try: + return self.Lookup(path) + except Exception: # pylint: disable=broad-except + pass + + raise ImportError("Could not load %s." % libname) + + def getpaths(self, libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # search through a prioritized series of locations for the library + + # we first search any specific directories identified by user + for dir_i in self.other_dirs: + for fmt in self.name_formats: + # dir_i should be absolute already + yield os.path.join(dir_i, fmt % libname) + + # check if this code is even stored in a physical file + try: + this_file = __file__ + except NameError: + this_file = None + + # then we search the directory where the generated python interface is stored + if this_file is not None: + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) + + # now, use the ctypes tools to try to find the library + for fmt in self.name_formats: + path = ctypes.util.find_library(fmt % libname) + if path: + yield path + + # then we search all paths identified as platform-specific lib paths + for path in self.getplatformpaths(libname): + yield path + + # Finally, we'll try the users current working directory + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) + + def getplatformpaths(self, _libname): # pylint: disable=no-self-use + """Return all the library paths available in this platform""" + return [] + + +# Darwin (Mac OS X) + + +class DarwinLibraryLoader(LibraryLoader): + """Library loader for MacOS""" + + name_formats = [ + "lib%s.dylib", + "lib%s.so", + "lib%s.bundle", + "%s.dylib", + "%s.so", + "%s.bundle", + "%s", + ] + + class Lookup(LibraryLoader.Lookup): + """ + Looking up library files for this platform (Darwin aka MacOS) + """ + + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + mode = ctypes.RTLD_GLOBAL + + def getplatformpaths(self, libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [fmt % libname for fmt in self.name_formats] + + for directory in self.getdirs(libname): + for name in names: + yield os.path.join(directory, name) + + @staticmethod + def getdirs(libname): + """Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + """ + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/usr/lib", + ] + + dirs = [] + + if "/" in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + dirs.extend(_environ_path("LD_RUN_PATH")) + + if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": + dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) + + dirs.extend(dyld_fallback_library_path) + + return dirs + + +# Posix + + +class PosixLibraryLoader(LibraryLoader): + """Library loader for POSIX-like systems (including Linux)""" + + _ld_so_cache = None + + _include = re.compile(r"^\s*include\s+(?P.*)") + + name_formats = ["lib%s.so", "%s.so", "%s"] + + class _Directories(dict): + """Deal with directories""" + + def __init__(self): + dict.__init__(self) + self.order = 0 + + def add(self, directory): + """Add a directory to our current set of directories""" + if len(directory) > 1: + directory = directory.rstrip(os.path.sep) + # only adds and updates order if exists and not already in set + if not os.path.exists(directory): + return + order = self.setdefault(directory, self.order) + if order == self.order: + self.order += 1 + + def extend(self, directories): + """Add a list of directories to our set""" + for a_dir in directories: + self.add(a_dir) + + def ordered(self): + """Sort the list of directories""" + return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) + + def _get_ld_so_conf_dirs(self, conf, dirs): + """ + Recursive function to help parse all ld.so.conf files, including proper + handling of the `include` directive. + """ + + try: + with open(conf) as fileobj: + for dirname in fileobj: + dirname = dirname.strip() + if not dirname: + continue + + match = self._include.match(dirname) + if not match: + dirs.add(dirname) + else: + for dir2 in glob.glob(match.group("pattern")): + self._get_ld_so_conf_dirs(dir2, dirs) + except IOError: + pass + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = self._Directories() + for name in ( + "LD_LIBRARY_PATH", + "SHLIB_PATH", # HP-UX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + + self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) + + bitage = platform.architecture()[0] + + unix_lib_dirs_list = [] + if bitage.startswith("64"): + # prefer 64 bit if that is our arch + unix_lib_dirs_list += ["/lib64", "/usr/lib64"] + + # must include standard libs, since those paths are also used by 64 bit + # installs + unix_lib_dirs_list += ["/lib", "/usr/lib"] + if sys.platform.startswith("linux"): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + if bitage.startswith("32"): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] + elif bitage.startswith("64"): + # Assume Intel/AMD x86 compatible + unix_lib_dirs_list += [ + "/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu", + ] + else: + # guess... + unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r"lib(.*)\.s[ol]") + # ext_re = re.compile(r"\.s[ol]$") + for our_dir in directories.ordered(): + try: + for path in glob.glob("%s/*.s[ol]*" % our_dir): + file = os.path.basename(path) + + # Index by filename + cache_i = cache.setdefault(file, set()) + cache_i.add(path) + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + cache_i = cache.setdefault(library, set()) + cache_i.add(path) + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname, set()) + for i in result: + # we iterate through all found paths for library, since we may have + # actually found multiple architectures or other library types that + # may not load + yield i + + +# Windows + + +class WindowsLibraryLoader(LibraryLoader): + """Library loader for Microsoft Windows""" + + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] + + class Lookup(LibraryLoader.Lookup): + """Lookup class for Windows libraries...""" + + def __init__(self, path): + super(WindowsLibraryLoader.Lookup, self).__init__(path) + self.access["stdcall"] = ctypes.windll.LoadLibrary(path) + + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader, + "msys": WindowsLibraryLoader, +} + +load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() + + +def add_library_search_dirs(other_dirs): + """ + Add libraries to search paths. + If library paths are relative, convert them to absolute with respect to this + file's directory + """ + for path in other_dirs: + if not os.path.isabs(path): + path = os.path.abspath(path) + load_library.other_dirs.append(path) + + +del loaderclass + +# End loader + +add_library_search_dirs([]) + +# No libraries + +# No modules + +# /jrtc/sample_apps/jbpf_codelets/data_generator/generated_data.h: 7 +class struct_anon_1(Structure): + pass + +struct_anon_1.__slots__ = [ + 'cnt', +] +struct_anon_1._fields_ = [ + ('cnt', c_int), +] + +example_msg = struct_anon_1# /jrtc/sample_apps/jbpf_codelets/data_generator/generated_data.h: 7 + +# No inserted files + +# No prefix-stripping + diff --git a/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py b/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py new file mode 100644 index 00000000..be33a5c0 --- /dev/null +++ b/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py @@ -0,0 +1,1012 @@ +r"""Wrapper for generated_data.pb.h + +Generated with: +/usr/local/bin/ctypesgen -I/jrtc/jbpf-protobuf/3p/nanopb generated_data.pb.h -o generated_data_pb.py + +Do not modify this file. +""" + +__docformat__ = "restructuredtext" + +# Begin preamble for Python + +import ctypes +import sys +from ctypes import * # noqa: F401, F403 + +_int_types = (ctypes.c_int16, ctypes.c_int32) +if hasattr(ctypes, "c_int64"): + # Some builds of ctypes apparently do not have ctypes.c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (ctypes.c_int64,) +for t in _int_types: + if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): + c_ptrdiff_t = t +del t +del _int_types + + + +class UserString: + def __init__(self, seq): + if isinstance(seq, bytes): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq).encode() + + def __bytes__(self): + return self.data + + def __str__(self): + return self.data.decode() + + def __repr__(self): + return repr(self.data) + + def __int__(self): + return int(self.data.decode()) + + def __long__(self): + return int(self.data.decode()) + + def __float__(self): + return float(self.data.decode()) + + def __complex__(self): + return complex(self.data.decode()) + + def __hash__(self): + return hash(self.data) + + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + else: + return self.data <= string + + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + else: + return self.data < string + + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + else: + return self.data >= string + + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + else: + return self.data > string + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + else: + return self.data == string + + def __ne__(self, string): + if isinstance(string, UserString): + return self.data != string.data + else: + return self.data != string + + def __contains__(self, char): + return char in self.data + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + return self.__class__(self.data[index]) + + def __getslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, bytes): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other).encode()) + + def __radd__(self, other): + if isinstance(other, bytes): + return self.__class__(other + self.data) + else: + return self.__class__(str(other).encode() + self.data) + + def __mul__(self, n): + return self.__class__(self.data * n) + + __rmul__ = __mul__ + + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): + return self.__class__(self.data.capitalize()) + + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + + def count(self, sub, start=0, end=sys.maxsize): + return self.data.count(sub, start, end) + + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + + def endswith(self, suffix, start=0, end=sys.maxsize): + return self.data.endswith(suffix, start, end) + + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + + def find(self, sub, start=0, end=sys.maxsize): + return self.data.find(sub, start, end) + + def index(self, sub, start=0, end=sys.maxsize): + return self.data.index(sub, start, end) + + def isalpha(self): + return self.data.isalpha() + + def isalnum(self): + return self.data.isalnum() + + def isdecimal(self): + return self.data.isdecimal() + + def isdigit(self): + return self.data.isdigit() + + def islower(self): + return self.data.islower() + + def isnumeric(self): + return self.data.isnumeric() + + def isspace(self): + return self.data.isspace() + + def istitle(self): + return self.data.istitle() + + def isupper(self): + return self.data.isupper() + + def join(self, seq): + return self.data.join(seq) + + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + + def lower(self): + return self.__class__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__class__(self.data.lstrip(chars)) + + def partition(self, sep): + return self.data.partition(sep) + + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + + def rfind(self, sub, start=0, end=sys.maxsize): + return self.data.rfind(sub, start, end) + + def rindex(self, sub, start=0, end=sys.maxsize): + return self.data.rindex(sub, start, end) + + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return self.data.rpartition(sep) + + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + + def splitlines(self, keepends=0): + return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): + return self.data.startswith(prefix, start, end) + + def strip(self, chars=None): + return self.__class__(self.data.strip(chars)) + + def swapcase(self): + return self.__class__(self.data.swapcase()) + + def title(self): + return self.__class__(self.data.title()) + + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + + def upper(self): + return self.__class__(self.data.upper()) + + def zfill(self, width): + return self.__class__(self.data.zfill(width)) + + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + + def __init__(self, string=""): + self.data = string + + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + sub + self.data[index + 1 :] + + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + self.data[index + 1 :] + + def __setslice__(self, start, end, sub): + start = max(start, 0) + end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start] + sub.data + self.data[end:] + elif isinstance(sub, bytes): + self.data = self.data[:start] + sub + self.data[end:] + else: + self.data = self.data[:start] + str(sub).encode() + self.data[end:] + + def __delslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + + def immutable(self): + return UserString(self.data) + + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, bytes): + self.data += other + else: + self.data += str(other).encode() + return self + + def __imul__(self, n): + self.data *= n + return self + + +class String(MutableString, ctypes.Union): + + _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] + + def __init__(self, obj=b""): + if isinstance(obj, (bytes, UserString)): + self.data = bytes(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(ctypes.POINTER(ctypes.c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from bytes + elif isinstance(obj, bytes): + return cls(obj) + + # Convert from str + elif isinstance(obj, str): + return cls(obj.encode()) + + # Convert from c_char_p + elif isinstance(obj, ctypes.c_char_p): + return obj + + # Convert from POINTER(ctypes.c_char) + elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) + + # Convert from ctypes.c_char array + elif isinstance(obj, ctypes.c_char * len(obj)): + return obj + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + + from_param = classmethod(from_param) + + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to ctypes.c_void_p. +def UNCHECKED(type): + if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": + return type + else: + return ctypes.c_void_p + + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self, func, restype, argtypes, errcheck): + self.func = func + self.func.restype = restype + self.argtypes = argtypes + if errcheck: + self.func.errcheck = errcheck + + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.func(*fixed_args + list(args[i:])) + + +def ord_if_char(value): + """ + Simple helper used for casts to simple builtin types: if the argument is a + string type, it will be converted to it's ordinal value. + + This function will raise an exception if the argument is string with more + than one characters. + """ + return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value + +# End preamble + +_libs = {} +_libdirs = [] + +# Begin loader + +""" +Load libraries - appropriately for all our supported platforms +""" +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import ctypes +import ctypes.util +import glob +import os.path +import platform +import re +import sys + + +def _environ_path(name): + """Split an environment variable into a path-like list elements""" + if name in os.environ: + return os.environ[name].split(":") + return [] + + +class LibraryLoader: + """ + A base class For loading of libraries ;-) + Subclasses load libraries for specific platforms. + """ + + # library names formatted specifically for platforms + name_formats = ["%s"] + + class Lookup: + """Looking up calling conventions for a platform""" + + mode = ctypes.DEFAULT_MODE + + def __init__(self, path): + super(LibraryLoader.Lookup, self).__init__() + self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) + + def get(self, name, calling_convention="cdecl"): + """Return the given name according to the selected calling convention""" + if calling_convention not in self.access: + raise LookupError( + "Unknown calling convention '{}' for function '{}'".format( + calling_convention, name + ) + ) + return getattr(self.access[calling_convention], name) + + def has(self, name, calling_convention="cdecl"): + """Return True if this given calling convention finds the given 'name'""" + if calling_convention not in self.access: + return False + return hasattr(self.access[calling_convention], name) + + def __getattr__(self, name): + return getattr(self.access["cdecl"], name) + + def __init__(self): + self.other_dirs = [] + + def __call__(self, libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + # noinspection PyBroadException + try: + return self.Lookup(path) + except Exception: # pylint: disable=broad-except + pass + + raise ImportError("Could not load %s." % libname) + + def getpaths(self, libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # search through a prioritized series of locations for the library + + # we first search any specific directories identified by user + for dir_i in self.other_dirs: + for fmt in self.name_formats: + # dir_i should be absolute already + yield os.path.join(dir_i, fmt % libname) + + # check if this code is even stored in a physical file + try: + this_file = __file__ + except NameError: + this_file = None + + # then we search the directory where the generated python interface is stored + if this_file is not None: + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) + + # now, use the ctypes tools to try to find the library + for fmt in self.name_formats: + path = ctypes.util.find_library(fmt % libname) + if path: + yield path + + # then we search all paths identified as platform-specific lib paths + for path in self.getplatformpaths(libname): + yield path + + # Finally, we'll try the users current working directory + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) + + def getplatformpaths(self, _libname): # pylint: disable=no-self-use + """Return all the library paths available in this platform""" + return [] + + +# Darwin (Mac OS X) + + +class DarwinLibraryLoader(LibraryLoader): + """Library loader for MacOS""" + + name_formats = [ + "lib%s.dylib", + "lib%s.so", + "lib%s.bundle", + "%s.dylib", + "%s.so", + "%s.bundle", + "%s", + ] + + class Lookup(LibraryLoader.Lookup): + """ + Looking up library files for this platform (Darwin aka MacOS) + """ + + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + mode = ctypes.RTLD_GLOBAL + + def getplatformpaths(self, libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [fmt % libname for fmt in self.name_formats] + + for directory in self.getdirs(libname): + for name in names: + yield os.path.join(directory, name) + + @staticmethod + def getdirs(libname): + """Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + """ + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/usr/lib", + ] + + dirs = [] + + if "/" in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + dirs.extend(_environ_path("LD_RUN_PATH")) + + if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": + dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) + + dirs.extend(dyld_fallback_library_path) + + return dirs + + +# Posix + + +class PosixLibraryLoader(LibraryLoader): + """Library loader for POSIX-like systems (including Linux)""" + + _ld_so_cache = None + + _include = re.compile(r"^\s*include\s+(?P.*)") + + name_formats = ["lib%s.so", "%s.so", "%s"] + + class _Directories(dict): + """Deal with directories""" + + def __init__(self): + dict.__init__(self) + self.order = 0 + + def add(self, directory): + """Add a directory to our current set of directories""" + if len(directory) > 1: + directory = directory.rstrip(os.path.sep) + # only adds and updates order if exists and not already in set + if not os.path.exists(directory): + return + order = self.setdefault(directory, self.order) + if order == self.order: + self.order += 1 + + def extend(self, directories): + """Add a list of directories to our set""" + for a_dir in directories: + self.add(a_dir) + + def ordered(self): + """Sort the list of directories""" + return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) + + def _get_ld_so_conf_dirs(self, conf, dirs): + """ + Recursive function to help parse all ld.so.conf files, including proper + handling of the `include` directive. + """ + + try: + with open(conf) as fileobj: + for dirname in fileobj: + dirname = dirname.strip() + if not dirname: + continue + + match = self._include.match(dirname) + if not match: + dirs.add(dirname) + else: + for dir2 in glob.glob(match.group("pattern")): + self._get_ld_so_conf_dirs(dir2, dirs) + except IOError: + pass + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = self._Directories() + for name in ( + "LD_LIBRARY_PATH", + "SHLIB_PATH", # HP-UX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + + self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) + + bitage = platform.architecture()[0] + + unix_lib_dirs_list = [] + if bitage.startswith("64"): + # prefer 64 bit if that is our arch + unix_lib_dirs_list += ["/lib64", "/usr/lib64"] + + # must include standard libs, since those paths are also used by 64 bit + # installs + unix_lib_dirs_list += ["/lib", "/usr/lib"] + if sys.platform.startswith("linux"): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + if bitage.startswith("32"): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] + elif bitage.startswith("64"): + # Assume Intel/AMD x86 compatible + unix_lib_dirs_list += [ + "/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu", + ] + else: + # guess... + unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r"lib(.*)\.s[ol]") + # ext_re = re.compile(r"\.s[ol]$") + for our_dir in directories.ordered(): + try: + for path in glob.glob("%s/*.s[ol]*" % our_dir): + file = os.path.basename(path) + + # Index by filename + cache_i = cache.setdefault(file, set()) + cache_i.add(path) + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + cache_i = cache.setdefault(library, set()) + cache_i.add(path) + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname, set()) + for i in result: + # we iterate through all found paths for library, since we may have + # actually found multiple architectures or other library types that + # may not load + yield i + + +# Windows + + +class WindowsLibraryLoader(LibraryLoader): + """Library loader for Microsoft Windows""" + + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] + + class Lookup(LibraryLoader.Lookup): + """Lookup class for Windows libraries...""" + + def __init__(self, path): + super(WindowsLibraryLoader.Lookup, self).__init__(path) + self.access["stdcall"] = ctypes.windll.LoadLibrary(path) + + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader, + "msys": WindowsLibraryLoader, +} + +load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() + + +def add_library_search_dirs(other_dirs): + """ + Add libraries to search paths. + If library paths are relative, convert them to absolute with respect to this + file's directory + """ + for path in other_dirs: + if not os.path.isabs(path): + path = os.path.abspath(path) + load_library.other_dirs.append(path) + + +del loaderclass + +# End loader + +add_library_search_dirs([]) + +# No libraries + +# No modules + +__uint8_t = c_ubyte# /usr/include/x86_64-linux-gnu/bits/types.h: 38 + +__uint16_t = c_ushort# /usr/include/x86_64-linux-gnu/bits/types.h: 40 + +__uint32_t = c_uint# /usr/include/x86_64-linux-gnu/bits/types.h: 42 + +__uint_least16_t = __uint16_t# /usr/include/x86_64-linux-gnu/bits/types.h: 55 + +uint8_t = __uint8_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 24 + +uint32_t = __uint32_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 26 + +uint_least16_t = __uint_least16_t# /usr/include/stdint.h: 50 + +pb_byte_t = uint8_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 241 + +pb_type_t = pb_byte_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 250 + +pb_size_t = uint_least16_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 326 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 +class struct_pb_istream_s(Structure): + pass + +pb_istream_t = struct_pb_istream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 +class struct_pb_ostream_s(Structure): + pass + +pb_ostream_t = struct_pb_ostream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 353 +class struct_pb_field_iter_s(Structure): + pass + +pb_field_iter_t = struct_pb_field_iter_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 334 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 340 +class struct_pb_msgdesc_s(Structure): + pass + +pb_msgdesc_t = struct_pb_msgdesc_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 339 + +struct_pb_msgdesc_s.__slots__ = [ + 'field_info', + 'submsg_info', + 'default_value', + 'field_callback', + 'field_count', + 'required_field_count', + 'largest_tag', +] +struct_pb_msgdesc_s._fields_ = [ + ('field_info', POINTER(uint32_t)), + ('submsg_info', POINTER(POINTER(pb_msgdesc_t))), + ('default_value', POINTER(pb_byte_t)), + ('field_callback', CFUNCTYPE(UNCHECKED(c_bool), POINTER(pb_istream_t), POINTER(pb_ostream_t), POINTER(pb_field_iter_t))), + ('field_count', pb_size_t), + ('required_field_count', pb_size_t), + ('largest_tag', pb_size_t), +] + +struct_pb_field_iter_s.__slots__ = [ + 'descriptor', + 'message', + 'index', + 'field_info_index', + 'required_field_index', + 'submessage_index', + 'tag', + 'data_size', + 'array_size', + 'type', + 'pField', + 'pData', + 'pSize', + 'submsg_desc', +] +struct_pb_field_iter_s._fields_ = [ + ('descriptor', POINTER(pb_msgdesc_t)), + ('message', POINTER(None)), + ('index', pb_size_t), + ('field_info_index', pb_size_t), + ('required_field_index', pb_size_t), + ('submessage_index', pb_size_t), + ('tag', pb_size_t), + ('data_size', pb_size_t), + ('array_size', pb_size_t), + ('type', pb_type_t), + ('pField', POINTER(None)), + ('pData', POINTER(None)), + ('pSize', POINTER(None)), + ('submsg_desc', POINTER(pb_msgdesc_t)), +] + +# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 15 +class struct__example_msg_pb(Structure): + pass + +struct__example_msg_pb.__slots__ = [ + 'cnt', +] +struct__example_msg_pb._fields_ = [ + ('cnt', uint32_t), +] + +example_msg_pb = struct__example_msg_pb# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 15 + +# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 35 +for _lib in _libs.values(): + try: + example_msg_pb_msg = (pb_msgdesc_t).in_dll(_lib, "example_msg_pb_msg") + break + except: + pass + +# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 27 +try: + example_msg_pb_cnt_tag = 1 +except: + pass + +# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 38 +try: + example_msg_pb_fields = pointer(example_msg_pb_msg) +except: + pass + +# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 41 +try: + GENERATED_DATA_PB_H_MAX_SIZE = example_msg_pb_size +except: + pass + +# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 42 +try: + example_msg_pb_size = 6 +except: + pass + +_example_msg_pb = struct__example_msg_pb# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 15 + +# No inserted files + +# No prefix-stripping + diff --git a/sample_apps/jbpf_codelets/simple_input/simple_input.py b/sample_apps/jbpf_codelets/simple_input/simple_input.py new file mode 100644 index 00000000..10c49cb7 --- /dev/null +++ b/sample_apps/jbpf_codelets/simple_input/simple_input.py @@ -0,0 +1,882 @@ +r"""Wrapper for simple_input.h + +Generated with: +/usr/local/bin/ctypesgen simple_input.h -o simple_input.py + +Do not modify this file. +""" + +__docformat__ = "restructuredtext" + +# Begin preamble for Python + +import ctypes +import sys +from ctypes import * # noqa: F401, F403 + +_int_types = (ctypes.c_int16, ctypes.c_int32) +if hasattr(ctypes, "c_int64"): + # Some builds of ctypes apparently do not have ctypes.c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (ctypes.c_int64,) +for t in _int_types: + if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): + c_ptrdiff_t = t +del t +del _int_types + + + +class UserString: + def __init__(self, seq): + if isinstance(seq, bytes): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq).encode() + + def __bytes__(self): + return self.data + + def __str__(self): + return self.data.decode() + + def __repr__(self): + return repr(self.data) + + def __int__(self): + return int(self.data.decode()) + + def __long__(self): + return int(self.data.decode()) + + def __float__(self): + return float(self.data.decode()) + + def __complex__(self): + return complex(self.data.decode()) + + def __hash__(self): + return hash(self.data) + + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + else: + return self.data <= string + + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + else: + return self.data < string + + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + else: + return self.data >= string + + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + else: + return self.data > string + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + else: + return self.data == string + + def __ne__(self, string): + if isinstance(string, UserString): + return self.data != string.data + else: + return self.data != string + + def __contains__(self, char): + return char in self.data + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + return self.__class__(self.data[index]) + + def __getslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, bytes): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other).encode()) + + def __radd__(self, other): + if isinstance(other, bytes): + return self.__class__(other + self.data) + else: + return self.__class__(str(other).encode() + self.data) + + def __mul__(self, n): + return self.__class__(self.data * n) + + __rmul__ = __mul__ + + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): + return self.__class__(self.data.capitalize()) + + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + + def count(self, sub, start=0, end=sys.maxsize): + return self.data.count(sub, start, end) + + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + + def endswith(self, suffix, start=0, end=sys.maxsize): + return self.data.endswith(suffix, start, end) + + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + + def find(self, sub, start=0, end=sys.maxsize): + return self.data.find(sub, start, end) + + def index(self, sub, start=0, end=sys.maxsize): + return self.data.index(sub, start, end) + + def isalpha(self): + return self.data.isalpha() + + def isalnum(self): + return self.data.isalnum() + + def isdecimal(self): + return self.data.isdecimal() + + def isdigit(self): + return self.data.isdigit() + + def islower(self): + return self.data.islower() + + def isnumeric(self): + return self.data.isnumeric() + + def isspace(self): + return self.data.isspace() + + def istitle(self): + return self.data.istitle() + + def isupper(self): + return self.data.isupper() + + def join(self, seq): + return self.data.join(seq) + + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + + def lower(self): + return self.__class__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__class__(self.data.lstrip(chars)) + + def partition(self, sep): + return self.data.partition(sep) + + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + + def rfind(self, sub, start=0, end=sys.maxsize): + return self.data.rfind(sub, start, end) + + def rindex(self, sub, start=0, end=sys.maxsize): + return self.data.rindex(sub, start, end) + + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return self.data.rpartition(sep) + + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + + def splitlines(self, keepends=0): + return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): + return self.data.startswith(prefix, start, end) + + def strip(self, chars=None): + return self.__class__(self.data.strip(chars)) + + def swapcase(self): + return self.__class__(self.data.swapcase()) + + def title(self): + return self.__class__(self.data.title()) + + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + + def upper(self): + return self.__class__(self.data.upper()) + + def zfill(self, width): + return self.__class__(self.data.zfill(width)) + + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + + def __init__(self, string=""): + self.data = string + + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + sub + self.data[index + 1 :] + + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + self.data[index + 1 :] + + def __setslice__(self, start, end, sub): + start = max(start, 0) + end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start] + sub.data + self.data[end:] + elif isinstance(sub, bytes): + self.data = self.data[:start] + sub + self.data[end:] + else: + self.data = self.data[:start] + str(sub).encode() + self.data[end:] + + def __delslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + + def immutable(self): + return UserString(self.data) + + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, bytes): + self.data += other + else: + self.data += str(other).encode() + return self + + def __imul__(self, n): + self.data *= n + return self + + +class String(MutableString, ctypes.Union): + + _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] + + def __init__(self, obj=b""): + if isinstance(obj, (bytes, UserString)): + self.data = bytes(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(ctypes.POINTER(ctypes.c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from bytes + elif isinstance(obj, bytes): + return cls(obj) + + # Convert from str + elif isinstance(obj, str): + return cls(obj.encode()) + + # Convert from c_char_p + elif isinstance(obj, ctypes.c_char_p): + return obj + + # Convert from POINTER(ctypes.c_char) + elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) + + # Convert from ctypes.c_char array + elif isinstance(obj, ctypes.c_char * len(obj)): + return obj + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + + from_param = classmethod(from_param) + + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to ctypes.c_void_p. +def UNCHECKED(type): + if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": + return type + else: + return ctypes.c_void_p + + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self, func, restype, argtypes, errcheck): + self.func = func + self.func.restype = restype + self.argtypes = argtypes + if errcheck: + self.func.errcheck = errcheck + + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.func(*fixed_args + list(args[i:])) + + +def ord_if_char(value): + """ + Simple helper used for casts to simple builtin types: if the argument is a + string type, it will be converted to it's ordinal value. + + This function will raise an exception if the argument is string with more + than one characters. + """ + return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value + +# End preamble + +_libs = {} +_libdirs = [] + +# Begin loader + +""" +Load libraries - appropriately for all our supported platforms +""" +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import ctypes +import ctypes.util +import glob +import os.path +import platform +import re +import sys + + +def _environ_path(name): + """Split an environment variable into a path-like list elements""" + if name in os.environ: + return os.environ[name].split(":") + return [] + + +class LibraryLoader: + """ + A base class For loading of libraries ;-) + Subclasses load libraries for specific platforms. + """ + + # library names formatted specifically for platforms + name_formats = ["%s"] + + class Lookup: + """Looking up calling conventions for a platform""" + + mode = ctypes.DEFAULT_MODE + + def __init__(self, path): + super(LibraryLoader.Lookup, self).__init__() + self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) + + def get(self, name, calling_convention="cdecl"): + """Return the given name according to the selected calling convention""" + if calling_convention not in self.access: + raise LookupError( + "Unknown calling convention '{}' for function '{}'".format( + calling_convention, name + ) + ) + return getattr(self.access[calling_convention], name) + + def has(self, name, calling_convention="cdecl"): + """Return True if this given calling convention finds the given 'name'""" + if calling_convention not in self.access: + return False + return hasattr(self.access[calling_convention], name) + + def __getattr__(self, name): + return getattr(self.access["cdecl"], name) + + def __init__(self): + self.other_dirs = [] + + def __call__(self, libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + # noinspection PyBroadException + try: + return self.Lookup(path) + except Exception: # pylint: disable=broad-except + pass + + raise ImportError("Could not load %s." % libname) + + def getpaths(self, libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # search through a prioritized series of locations for the library + + # we first search any specific directories identified by user + for dir_i in self.other_dirs: + for fmt in self.name_formats: + # dir_i should be absolute already + yield os.path.join(dir_i, fmt % libname) + + # check if this code is even stored in a physical file + try: + this_file = __file__ + except NameError: + this_file = None + + # then we search the directory where the generated python interface is stored + if this_file is not None: + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) + + # now, use the ctypes tools to try to find the library + for fmt in self.name_formats: + path = ctypes.util.find_library(fmt % libname) + if path: + yield path + + # then we search all paths identified as platform-specific lib paths + for path in self.getplatformpaths(libname): + yield path + + # Finally, we'll try the users current working directory + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) + + def getplatformpaths(self, _libname): # pylint: disable=no-self-use + """Return all the library paths available in this platform""" + return [] + + +# Darwin (Mac OS X) + + +class DarwinLibraryLoader(LibraryLoader): + """Library loader for MacOS""" + + name_formats = [ + "lib%s.dylib", + "lib%s.so", + "lib%s.bundle", + "%s.dylib", + "%s.so", + "%s.bundle", + "%s", + ] + + class Lookup(LibraryLoader.Lookup): + """ + Looking up library files for this platform (Darwin aka MacOS) + """ + + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + mode = ctypes.RTLD_GLOBAL + + def getplatformpaths(self, libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [fmt % libname for fmt in self.name_formats] + + for directory in self.getdirs(libname): + for name in names: + yield os.path.join(directory, name) + + @staticmethod + def getdirs(libname): + """Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + """ + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/usr/lib", + ] + + dirs = [] + + if "/" in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + dirs.extend(_environ_path("LD_RUN_PATH")) + + if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": + dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) + + dirs.extend(dyld_fallback_library_path) + + return dirs + + +# Posix + + +class PosixLibraryLoader(LibraryLoader): + """Library loader for POSIX-like systems (including Linux)""" + + _ld_so_cache = None + + _include = re.compile(r"^\s*include\s+(?P.*)") + + name_formats = ["lib%s.so", "%s.so", "%s"] + + class _Directories(dict): + """Deal with directories""" + + def __init__(self): + dict.__init__(self) + self.order = 0 + + def add(self, directory): + """Add a directory to our current set of directories""" + if len(directory) > 1: + directory = directory.rstrip(os.path.sep) + # only adds and updates order if exists and not already in set + if not os.path.exists(directory): + return + order = self.setdefault(directory, self.order) + if order == self.order: + self.order += 1 + + def extend(self, directories): + """Add a list of directories to our set""" + for a_dir in directories: + self.add(a_dir) + + def ordered(self): + """Sort the list of directories""" + return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) + + def _get_ld_so_conf_dirs(self, conf, dirs): + """ + Recursive function to help parse all ld.so.conf files, including proper + handling of the `include` directive. + """ + + try: + with open(conf) as fileobj: + for dirname in fileobj: + dirname = dirname.strip() + if not dirname: + continue + + match = self._include.match(dirname) + if not match: + dirs.add(dirname) + else: + for dir2 in glob.glob(match.group("pattern")): + self._get_ld_so_conf_dirs(dir2, dirs) + except IOError: + pass + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = self._Directories() + for name in ( + "LD_LIBRARY_PATH", + "SHLIB_PATH", # HP-UX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + + self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) + + bitage = platform.architecture()[0] + + unix_lib_dirs_list = [] + if bitage.startswith("64"): + # prefer 64 bit if that is our arch + unix_lib_dirs_list += ["/lib64", "/usr/lib64"] + + # must include standard libs, since those paths are also used by 64 bit + # installs + unix_lib_dirs_list += ["/lib", "/usr/lib"] + if sys.platform.startswith("linux"): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + if bitage.startswith("32"): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] + elif bitage.startswith("64"): + # Assume Intel/AMD x86 compatible + unix_lib_dirs_list += [ + "/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu", + ] + else: + # guess... + unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r"lib(.*)\.s[ol]") + # ext_re = re.compile(r"\.s[ol]$") + for our_dir in directories.ordered(): + try: + for path in glob.glob("%s/*.s[ol]*" % our_dir): + file = os.path.basename(path) + + # Index by filename + cache_i = cache.setdefault(file, set()) + cache_i.add(path) + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + cache_i = cache.setdefault(library, set()) + cache_i.add(path) + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname, set()) + for i in result: + # we iterate through all found paths for library, since we may have + # actually found multiple architectures or other library types that + # may not load + yield i + + +# Windows + + +class WindowsLibraryLoader(LibraryLoader): + """Library loader for Microsoft Windows""" + + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] + + class Lookup(LibraryLoader.Lookup): + """Lookup class for Windows libraries...""" + + def __init__(self, path): + super(WindowsLibraryLoader.Lookup, self).__init__(path) + self.access["stdcall"] = ctypes.windll.LoadLibrary(path) + + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader, + "msys": WindowsLibraryLoader, +} + +load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() + + +def add_library_search_dirs(other_dirs): + """ + Add libraries to search paths. + If library paths are relative, convert them to absolute with respect to this + file's directory + """ + for path in other_dirs: + if not os.path.isabs(path): + path = os.path.abspath(path) + load_library.other_dirs.append(path) + + +del loaderclass + +# End loader + +add_library_search_dirs([]) + +# No libraries + +# No modules + +# /jrtc/sample_apps/jbpf_codelets/simple_input/simple_input.h: 7 +class struct_anon_1(Structure): + pass + +struct_anon_1.__slots__ = [ + 'aggregate_counter', +] +struct_anon_1._fields_ = [ + ('aggregate_counter', c_int), +] + +simple_input = struct_anon_1# /jrtc/sample_apps/jbpf_codelets/simple_input/simple_input.h: 7 + +# No inserted files + +# No prefix-stripping + diff --git a/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py b/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py new file mode 100644 index 00000000..ce0e7170 --- /dev/null +++ b/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py @@ -0,0 +1,1012 @@ +r"""Wrapper for simple_input.pb.h + +Generated with: +/usr/local/bin/ctypesgen -I/jrtc/jbpf-protobuf/3p/nanopb simple_input.pb.h -o simple_input_pb.py + +Do not modify this file. +""" + +__docformat__ = "restructuredtext" + +# Begin preamble for Python + +import ctypes +import sys +from ctypes import * # noqa: F401, F403 + +_int_types = (ctypes.c_int16, ctypes.c_int32) +if hasattr(ctypes, "c_int64"): + # Some builds of ctypes apparently do not have ctypes.c_int64 + # defined; it's a pretty good bet that these builds do not + # have 64-bit pointers. + _int_types += (ctypes.c_int64,) +for t in _int_types: + if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): + c_ptrdiff_t = t +del t +del _int_types + + + +class UserString: + def __init__(self, seq): + if isinstance(seq, bytes): + self.data = seq + elif isinstance(seq, UserString): + self.data = seq.data[:] + else: + self.data = str(seq).encode() + + def __bytes__(self): + return self.data + + def __str__(self): + return self.data.decode() + + def __repr__(self): + return repr(self.data) + + def __int__(self): + return int(self.data.decode()) + + def __long__(self): + return int(self.data.decode()) + + def __float__(self): + return float(self.data.decode()) + + def __complex__(self): + return complex(self.data.decode()) + + def __hash__(self): + return hash(self.data) + + def __le__(self, string): + if isinstance(string, UserString): + return self.data <= string.data + else: + return self.data <= string + + def __lt__(self, string): + if isinstance(string, UserString): + return self.data < string.data + else: + return self.data < string + + def __ge__(self, string): + if isinstance(string, UserString): + return self.data >= string.data + else: + return self.data >= string + + def __gt__(self, string): + if isinstance(string, UserString): + return self.data > string.data + else: + return self.data > string + + def __eq__(self, string): + if isinstance(string, UserString): + return self.data == string.data + else: + return self.data == string + + def __ne__(self, string): + if isinstance(string, UserString): + return self.data != string.data + else: + return self.data != string + + def __contains__(self, char): + return char in self.data + + def __len__(self): + return len(self.data) + + def __getitem__(self, index): + return self.__class__(self.data[index]) + + def __getslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + return self.__class__(self.data[start:end]) + + def __add__(self, other): + if isinstance(other, UserString): + return self.__class__(self.data + other.data) + elif isinstance(other, bytes): + return self.__class__(self.data + other) + else: + return self.__class__(self.data + str(other).encode()) + + def __radd__(self, other): + if isinstance(other, bytes): + return self.__class__(other + self.data) + else: + return self.__class__(str(other).encode() + self.data) + + def __mul__(self, n): + return self.__class__(self.data * n) + + __rmul__ = __mul__ + + def __mod__(self, args): + return self.__class__(self.data % args) + + # the following methods are defined in alphabetical order: + def capitalize(self): + return self.__class__(self.data.capitalize()) + + def center(self, width, *args): + return self.__class__(self.data.center(width, *args)) + + def count(self, sub, start=0, end=sys.maxsize): + return self.data.count(sub, start, end) + + def decode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.decode(encoding, errors)) + else: + return self.__class__(self.data.decode(encoding)) + else: + return self.__class__(self.data.decode()) + + def encode(self, encoding=None, errors=None): # XXX improve this? + if encoding: + if errors: + return self.__class__(self.data.encode(encoding, errors)) + else: + return self.__class__(self.data.encode(encoding)) + else: + return self.__class__(self.data.encode()) + + def endswith(self, suffix, start=0, end=sys.maxsize): + return self.data.endswith(suffix, start, end) + + def expandtabs(self, tabsize=8): + return self.__class__(self.data.expandtabs(tabsize)) + + def find(self, sub, start=0, end=sys.maxsize): + return self.data.find(sub, start, end) + + def index(self, sub, start=0, end=sys.maxsize): + return self.data.index(sub, start, end) + + def isalpha(self): + return self.data.isalpha() + + def isalnum(self): + return self.data.isalnum() + + def isdecimal(self): + return self.data.isdecimal() + + def isdigit(self): + return self.data.isdigit() + + def islower(self): + return self.data.islower() + + def isnumeric(self): + return self.data.isnumeric() + + def isspace(self): + return self.data.isspace() + + def istitle(self): + return self.data.istitle() + + def isupper(self): + return self.data.isupper() + + def join(self, seq): + return self.data.join(seq) + + def ljust(self, width, *args): + return self.__class__(self.data.ljust(width, *args)) + + def lower(self): + return self.__class__(self.data.lower()) + + def lstrip(self, chars=None): + return self.__class__(self.data.lstrip(chars)) + + def partition(self, sep): + return self.data.partition(sep) + + def replace(self, old, new, maxsplit=-1): + return self.__class__(self.data.replace(old, new, maxsplit)) + + def rfind(self, sub, start=0, end=sys.maxsize): + return self.data.rfind(sub, start, end) + + def rindex(self, sub, start=0, end=sys.maxsize): + return self.data.rindex(sub, start, end) + + def rjust(self, width, *args): + return self.__class__(self.data.rjust(width, *args)) + + def rpartition(self, sep): + return self.data.rpartition(sep) + + def rstrip(self, chars=None): + return self.__class__(self.data.rstrip(chars)) + + def split(self, sep=None, maxsplit=-1): + return self.data.split(sep, maxsplit) + + def rsplit(self, sep=None, maxsplit=-1): + return self.data.rsplit(sep, maxsplit) + + def splitlines(self, keepends=0): + return self.data.splitlines(keepends) + + def startswith(self, prefix, start=0, end=sys.maxsize): + return self.data.startswith(prefix, start, end) + + def strip(self, chars=None): + return self.__class__(self.data.strip(chars)) + + def swapcase(self): + return self.__class__(self.data.swapcase()) + + def title(self): + return self.__class__(self.data.title()) + + def translate(self, *args): + return self.__class__(self.data.translate(*args)) + + def upper(self): + return self.__class__(self.data.upper()) + + def zfill(self, width): + return self.__class__(self.data.zfill(width)) + + +class MutableString(UserString): + """mutable string objects + + Python strings are immutable objects. This has the advantage, that + strings may be used as dictionary keys. If this property isn't needed + and you insist on changing string values in place instead, you may cheat + and use MutableString. + + But the purpose of this class is an educational one: to prevent + people from inventing their own mutable string class derived + from UserString and than forget thereby to remove (override) the + __hash__ method inherited from UserString. This would lead to + errors that would be very hard to track down. + + A faster and better solution is to rewrite your program using lists.""" + + def __init__(self, string=""): + self.data = string + + def __hash__(self): + raise TypeError("unhashable type (it is mutable)") + + def __setitem__(self, index, sub): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + sub + self.data[index + 1 :] + + def __delitem__(self, index): + if index < 0: + index += len(self.data) + if index < 0 or index >= len(self.data): + raise IndexError + self.data = self.data[:index] + self.data[index + 1 :] + + def __setslice__(self, start, end, sub): + start = max(start, 0) + end = max(end, 0) + if isinstance(sub, UserString): + self.data = self.data[:start] + sub.data + self.data[end:] + elif isinstance(sub, bytes): + self.data = self.data[:start] + sub + self.data[end:] + else: + self.data = self.data[:start] + str(sub).encode() + self.data[end:] + + def __delslice__(self, start, end): + start = max(start, 0) + end = max(end, 0) + self.data = self.data[:start] + self.data[end:] + + def immutable(self): + return UserString(self.data) + + def __iadd__(self, other): + if isinstance(other, UserString): + self.data += other.data + elif isinstance(other, bytes): + self.data += other + else: + self.data += str(other).encode() + return self + + def __imul__(self, n): + self.data *= n + return self + + +class String(MutableString, ctypes.Union): + + _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] + + def __init__(self, obj=b""): + if isinstance(obj, (bytes, UserString)): + self.data = bytes(obj) + else: + self.raw = obj + + def __len__(self): + return self.data and len(self.data) or 0 + + def from_param(cls, obj): + # Convert None or 0 + if obj is None or obj == 0: + return cls(ctypes.POINTER(ctypes.c_char)()) + + # Convert from String + elif isinstance(obj, String): + return obj + + # Convert from bytes + elif isinstance(obj, bytes): + return cls(obj) + + # Convert from str + elif isinstance(obj, str): + return cls(obj.encode()) + + # Convert from c_char_p + elif isinstance(obj, ctypes.c_char_p): + return obj + + # Convert from POINTER(ctypes.c_char) + elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): + return obj + + # Convert from raw pointer + elif isinstance(obj, int): + return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) + + # Convert from ctypes.c_char array + elif isinstance(obj, ctypes.c_char * len(obj)): + return obj + + # Convert from object + else: + return String.from_param(obj._as_parameter_) + + from_param = classmethod(from_param) + + +def ReturnString(obj, func=None, arguments=None): + return String.from_param(obj) + + +# As of ctypes 1.0, ctypes does not support custom error-checking +# functions on callbacks, nor does it support custom datatypes on +# callbacks, so we must ensure that all callbacks return +# primitive datatypes. +# +# Non-primitive return values wrapped with UNCHECKED won't be +# typechecked, and will be converted to ctypes.c_void_p. +def UNCHECKED(type): + if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": + return type + else: + return ctypes.c_void_p + + +# ctypes doesn't have direct support for variadic functions, so we have to write +# our own wrapper class +class _variadic_function(object): + def __init__(self, func, restype, argtypes, errcheck): + self.func = func + self.func.restype = restype + self.argtypes = argtypes + if errcheck: + self.func.errcheck = errcheck + + def _as_parameter_(self): + # So we can pass this variadic function as a function pointer + return self.func + + def __call__(self, *args): + fixed_args = [] + i = 0 + for argtype in self.argtypes: + # Typecheck what we can + fixed_args.append(argtype.from_param(args[i])) + i += 1 + return self.func(*fixed_args + list(args[i:])) + + +def ord_if_char(value): + """ + Simple helper used for casts to simple builtin types: if the argument is a + string type, it will be converted to it's ordinal value. + + This function will raise an exception if the argument is string with more + than one characters. + """ + return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value + +# End preamble + +_libs = {} +_libdirs = [] + +# Begin loader + +""" +Load libraries - appropriately for all our supported platforms +""" +# ---------------------------------------------------------------------------- +# Copyright (c) 2008 David James +# Copyright (c) 2006-2008 Alex Holkner +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of pyglet nor the names of its +# contributors may be used to endorse or promote products +# derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# ---------------------------------------------------------------------------- + +import ctypes +import ctypes.util +import glob +import os.path +import platform +import re +import sys + + +def _environ_path(name): + """Split an environment variable into a path-like list elements""" + if name in os.environ: + return os.environ[name].split(":") + return [] + + +class LibraryLoader: + """ + A base class For loading of libraries ;-) + Subclasses load libraries for specific platforms. + """ + + # library names formatted specifically for platforms + name_formats = ["%s"] + + class Lookup: + """Looking up calling conventions for a platform""" + + mode = ctypes.DEFAULT_MODE + + def __init__(self, path): + super(LibraryLoader.Lookup, self).__init__() + self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) + + def get(self, name, calling_convention="cdecl"): + """Return the given name according to the selected calling convention""" + if calling_convention not in self.access: + raise LookupError( + "Unknown calling convention '{}' for function '{}'".format( + calling_convention, name + ) + ) + return getattr(self.access[calling_convention], name) + + def has(self, name, calling_convention="cdecl"): + """Return True if this given calling convention finds the given 'name'""" + if calling_convention not in self.access: + return False + return hasattr(self.access[calling_convention], name) + + def __getattr__(self, name): + return getattr(self.access["cdecl"], name) + + def __init__(self): + self.other_dirs = [] + + def __call__(self, libname): + """Given the name of a library, load it.""" + paths = self.getpaths(libname) + + for path in paths: + # noinspection PyBroadException + try: + return self.Lookup(path) + except Exception: # pylint: disable=broad-except + pass + + raise ImportError("Could not load %s." % libname) + + def getpaths(self, libname): + """Return a list of paths where the library might be found.""" + if os.path.isabs(libname): + yield libname + else: + # search through a prioritized series of locations for the library + + # we first search any specific directories identified by user + for dir_i in self.other_dirs: + for fmt in self.name_formats: + # dir_i should be absolute already + yield os.path.join(dir_i, fmt % libname) + + # check if this code is even stored in a physical file + try: + this_file = __file__ + except NameError: + this_file = None + + # then we search the directory where the generated python interface is stored + if this_file is not None: + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) + + # now, use the ctypes tools to try to find the library + for fmt in self.name_formats: + path = ctypes.util.find_library(fmt % libname) + if path: + yield path + + # then we search all paths identified as platform-specific lib paths + for path in self.getplatformpaths(libname): + yield path + + # Finally, we'll try the users current working directory + for fmt in self.name_formats: + yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) + + def getplatformpaths(self, _libname): # pylint: disable=no-self-use + """Return all the library paths available in this platform""" + return [] + + +# Darwin (Mac OS X) + + +class DarwinLibraryLoader(LibraryLoader): + """Library loader for MacOS""" + + name_formats = [ + "lib%s.dylib", + "lib%s.so", + "lib%s.bundle", + "%s.dylib", + "%s.so", + "%s.bundle", + "%s", + ] + + class Lookup(LibraryLoader.Lookup): + """ + Looking up library files for this platform (Darwin aka MacOS) + """ + + # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead + # of the default RTLD_LOCAL. Without this, you end up with + # libraries not being loadable, resulting in "Symbol not found" + # errors + mode = ctypes.RTLD_GLOBAL + + def getplatformpaths(self, libname): + if os.path.pathsep in libname: + names = [libname] + else: + names = [fmt % libname for fmt in self.name_formats] + + for directory in self.getdirs(libname): + for name in names: + yield os.path.join(directory, name) + + @staticmethod + def getdirs(libname): + """Implements the dylib search as specified in Apple documentation: + + http://developer.apple.com/documentation/DeveloperTools/Conceptual/ + DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html + + Before commencing the standard search, the method first checks + the bundle's ``Frameworks`` directory if the application is running + within a bundle (OS X .app). + """ + + dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") + if not dyld_fallback_library_path: + dyld_fallback_library_path = [ + os.path.expanduser("~/lib"), + "/usr/local/lib", + "/usr/lib", + ] + + dirs = [] + + if "/" in libname: + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + else: + dirs.extend(_environ_path("LD_LIBRARY_PATH")) + dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) + dirs.extend(_environ_path("LD_RUN_PATH")) + + if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": + dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) + + dirs.extend(dyld_fallback_library_path) + + return dirs + + +# Posix + + +class PosixLibraryLoader(LibraryLoader): + """Library loader for POSIX-like systems (including Linux)""" + + _ld_so_cache = None + + _include = re.compile(r"^\s*include\s+(?P.*)") + + name_formats = ["lib%s.so", "%s.so", "%s"] + + class _Directories(dict): + """Deal with directories""" + + def __init__(self): + dict.__init__(self) + self.order = 0 + + def add(self, directory): + """Add a directory to our current set of directories""" + if len(directory) > 1: + directory = directory.rstrip(os.path.sep) + # only adds and updates order if exists and not already in set + if not os.path.exists(directory): + return + order = self.setdefault(directory, self.order) + if order == self.order: + self.order += 1 + + def extend(self, directories): + """Add a list of directories to our set""" + for a_dir in directories: + self.add(a_dir) + + def ordered(self): + """Sort the list of directories""" + return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) + + def _get_ld_so_conf_dirs(self, conf, dirs): + """ + Recursive function to help parse all ld.so.conf files, including proper + handling of the `include` directive. + """ + + try: + with open(conf) as fileobj: + for dirname in fileobj: + dirname = dirname.strip() + if not dirname: + continue + + match = self._include.match(dirname) + if not match: + dirs.add(dirname) + else: + for dir2 in glob.glob(match.group("pattern")): + self._get_ld_so_conf_dirs(dir2, dirs) + except IOError: + pass + + def _create_ld_so_cache(self): + # Recreate search path followed by ld.so. This is going to be + # slow to build, and incorrect (ld.so uses ld.so.cache, which may + # not be up-to-date). Used only as fallback for distros without + # /sbin/ldconfig. + # + # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. + + directories = self._Directories() + for name in ( + "LD_LIBRARY_PATH", + "SHLIB_PATH", # HP-UX + "LIBPATH", # OS/2, AIX + "LIBRARY_PATH", # BE/OS + ): + if name in os.environ: + directories.extend(os.environ[name].split(os.pathsep)) + + self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) + + bitage = platform.architecture()[0] + + unix_lib_dirs_list = [] + if bitage.startswith("64"): + # prefer 64 bit if that is our arch + unix_lib_dirs_list += ["/lib64", "/usr/lib64"] + + # must include standard libs, since those paths are also used by 64 bit + # installs + unix_lib_dirs_list += ["/lib", "/usr/lib"] + if sys.platform.startswith("linux"): + # Try and support multiarch work in Ubuntu + # https://wiki.ubuntu.com/MultiarchSpec + if bitage.startswith("32"): + # Assume Intel/AMD x86 compat + unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] + elif bitage.startswith("64"): + # Assume Intel/AMD x86 compatible + unix_lib_dirs_list += [ + "/lib/x86_64-linux-gnu", + "/usr/lib/x86_64-linux-gnu", + ] + else: + # guess... + unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") + directories.extend(unix_lib_dirs_list) + + cache = {} + lib_re = re.compile(r"lib(.*)\.s[ol]") + # ext_re = re.compile(r"\.s[ol]$") + for our_dir in directories.ordered(): + try: + for path in glob.glob("%s/*.s[ol]*" % our_dir): + file = os.path.basename(path) + + # Index by filename + cache_i = cache.setdefault(file, set()) + cache_i.add(path) + + # Index by library name + match = lib_re.match(file) + if match: + library = match.group(1) + cache_i = cache.setdefault(library, set()) + cache_i.add(path) + except OSError: + pass + + self._ld_so_cache = cache + + def getplatformpaths(self, libname): + if self._ld_so_cache is None: + self._create_ld_so_cache() + + result = self._ld_so_cache.get(libname, set()) + for i in result: + # we iterate through all found paths for library, since we may have + # actually found multiple architectures or other library types that + # may not load + yield i + + +# Windows + + +class WindowsLibraryLoader(LibraryLoader): + """Library loader for Microsoft Windows""" + + name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] + + class Lookup(LibraryLoader.Lookup): + """Lookup class for Windows libraries...""" + + def __init__(self, path): + super(WindowsLibraryLoader.Lookup, self).__init__(path) + self.access["stdcall"] = ctypes.windll.LoadLibrary(path) + + +# Platform switching + +# If your value of sys.platform does not appear in this dict, please contact +# the Ctypesgen maintainers. + +loaderclass = { + "darwin": DarwinLibraryLoader, + "cygwin": WindowsLibraryLoader, + "win32": WindowsLibraryLoader, + "msys": WindowsLibraryLoader, +} + +load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() + + +def add_library_search_dirs(other_dirs): + """ + Add libraries to search paths. + If library paths are relative, convert them to absolute with respect to this + file's directory + """ + for path in other_dirs: + if not os.path.isabs(path): + path = os.path.abspath(path) + load_library.other_dirs.append(path) + + +del loaderclass + +# End loader + +add_library_search_dirs([]) + +# No libraries + +# No modules + +__uint8_t = c_ubyte# /usr/include/x86_64-linux-gnu/bits/types.h: 38 + +__uint16_t = c_ushort# /usr/include/x86_64-linux-gnu/bits/types.h: 40 + +__uint32_t = c_uint# /usr/include/x86_64-linux-gnu/bits/types.h: 42 + +__uint_least16_t = __uint16_t# /usr/include/x86_64-linux-gnu/bits/types.h: 55 + +uint8_t = __uint8_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 24 + +uint32_t = __uint32_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 26 + +uint_least16_t = __uint_least16_t# /usr/include/stdint.h: 50 + +pb_byte_t = uint8_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 241 + +pb_type_t = pb_byte_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 250 + +pb_size_t = uint_least16_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 326 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 +class struct_pb_istream_s(Structure): + pass + +pb_istream_t = struct_pb_istream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 +class struct_pb_ostream_s(Structure): + pass + +pb_ostream_t = struct_pb_ostream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 353 +class struct_pb_field_iter_s(Structure): + pass + +pb_field_iter_t = struct_pb_field_iter_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 334 + +# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 340 +class struct_pb_msgdesc_s(Structure): + pass + +pb_msgdesc_t = struct_pb_msgdesc_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 339 + +struct_pb_msgdesc_s.__slots__ = [ + 'field_info', + 'submsg_info', + 'default_value', + 'field_callback', + 'field_count', + 'required_field_count', + 'largest_tag', +] +struct_pb_msgdesc_s._fields_ = [ + ('field_info', POINTER(uint32_t)), + ('submsg_info', POINTER(POINTER(pb_msgdesc_t))), + ('default_value', POINTER(pb_byte_t)), + ('field_callback', CFUNCTYPE(UNCHECKED(c_bool), POINTER(pb_istream_t), POINTER(pb_ostream_t), POINTER(pb_field_iter_t))), + ('field_count', pb_size_t), + ('required_field_count', pb_size_t), + ('largest_tag', pb_size_t), +] + +struct_pb_field_iter_s.__slots__ = [ + 'descriptor', + 'message', + 'index', + 'field_info_index', + 'required_field_index', + 'submessage_index', + 'tag', + 'data_size', + 'array_size', + 'type', + 'pField', + 'pData', + 'pSize', + 'submsg_desc', +] +struct_pb_field_iter_s._fields_ = [ + ('descriptor', POINTER(pb_msgdesc_t)), + ('message', POINTER(None)), + ('index', pb_size_t), + ('field_info_index', pb_size_t), + ('required_field_index', pb_size_t), + ('submessage_index', pb_size_t), + ('tag', pb_size_t), + ('data_size', pb_size_t), + ('array_size', pb_size_t), + ('type', pb_type_t), + ('pField', POINTER(None)), + ('pData', POINTER(None)), + ('pSize', POINTER(None)), + ('submsg_desc', POINTER(pb_msgdesc_t)), +] + +# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 15 +class struct__simple_input_pb(Structure): + pass + +struct__simple_input_pb.__slots__ = [ + 'aggregate_counter', +] +struct__simple_input_pb._fields_ = [ + ('aggregate_counter', c_int32), +] + +simple_input_pb = struct__simple_input_pb# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 15 + +# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 35 +for _lib in _libs.values(): + try: + simple_input_pb_msg = (pb_msgdesc_t).in_dll(_lib, "simple_input_pb_msg") + break + except: + pass + +# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 27 +try: + simple_input_pb_aggregate_counter_tag = 1 +except: + pass + +# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 38 +try: + simple_input_pb_fields = pointer(simple_input_pb_msg) +except: + pass + +# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 41 +try: + SIMPLE_INPUT_PB_H_MAX_SIZE = simple_input_pb_size +except: + pass + +# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 42 +try: + simple_input_pb_size = 11 +except: + pass + +_simple_input_pb = struct__simple_input_pb# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 15 + +# No inserted files + +# No prefix-stripping + diff --git a/src/wrapper_apis/python/jrtc_app.py b/src/wrapper_apis/python/jrtc_app.py index 2b5d8a81..ee852d3a 100644 --- a/src/wrapper_apis/python/jrtc_app.py +++ b/src/wrapper_apis/python/jrtc_app.py @@ -1,14 +1,16 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. - import time import os import sys import ctypes -from ctypes import c_int, c_float, c_char_p, c_void_p, c_bool +from ctypes import ( + c_int, c_float, c_char_p, c_void_p, c_bool, + POINTER, Structure, c_uint16, c_uint64 +) from dataclasses import dataclass -from typing import Any +from typing import Any, Optional # Retrieve the JRTC application path from environment variables JRTC_APP_PATH = os.environ.get("JRTC_APP_PATH") @@ -16,163 +18,251 @@ print("Warning: JRTC_APP_PATH not set") JRTC_APP_PATH = "./" sys.path.append(f"{JRTC_APP_PATH}") -from jrtc_bindings import * -# Import necessary JRTC modules -from jrtc_router_stream_id import ( - JrtcRouterStreamId, - jrtc_router_stream_id_matches_req +from jrtc_bindings import * +from jrtc_router_stream_id import JrtcRouterStreamId, jrtc_router_stream_id_matches_req +from jrtc_wrapper_utils import ( + JrtcAppEnv, + get_ctx_from_capsule, + get_data_entry_array_ptr, ) -from jrtc_wrapper_utils import JrtcAppEnv, get_ctx_from_capsule, get_data_entry_array_ptr from jrtc_router_lib import ( jrtc_router_channel_register_stream_id_req, jrtc_router_channel_deregister_stream_id_req, jrtc_router_receive, - jrtc_router_channel_send_input_msg, + jrtc_router_channel_send_input_msg, jrtc_router_channel_send_output_msg, - jrtc_router_channel_create, - jrtc_router_channel_destroy, + jrtc_router_channel_create, + jrtc_router_channel_destroy, jrtc_router_channel_release_buf, jrtc_router_input_channel_exists, JRTC_ROUTER_REQ_DEST_ANY, JRTC_ROUTER_REQ_DEVICE_ID_ANY, JRTC_ROUTER_REQ_DEST_NONE, JRTC_ROUTER_REQ_STREAM_PATH_ANY, - JRTC_ROUTER_REQ_STREAM_NAME_ANY + JRTC_ROUTER_REQ_STREAM_NAME_ANY, ) - - -# Load the shared C library -lib = ctypes.CDLL(f'{JRTC_APP_PATH}/libjrtc_app.so') - -# Define C structures (using ctypes) - -class JrtcApp(ctypes.Structure): - pass - -class JrtcStreamIdCfg_t(ctypes.Structure): +# Structs +class JrtcStreamIdCfg_t(Structure): _fields_ = [ ("destination", c_int), ("device_id", c_int), ("stream_source", c_char_p), - ("io_map", c_char_p) + ("io_map", c_char_p), ] -class JrtcAppChannelCfg_t(ctypes.Structure): - _fields_ = [ - ("is_output", c_bool), - ("num_elems", c_int), - ("elem_size", c_int) - ] +class JrtcAppChannelCfg_t(Structure): + _fields_ = [("is_output", c_bool), ("num_elems", c_int), ("elem_size", c_int)] -class JrtcStreamCfg_t(ctypes.Structure): +class JrtcStreamCfg_t(Structure): _fields_ = [ ("sid", JrtcStreamIdCfg_t), ("is_rx", c_bool), - ("appChannel", ctypes.POINTER(JrtcAppChannelCfg_t)) + ("appChannel", POINTER(JrtcAppChannelCfg_t)), ] -class JrtcAppCfg_t(ctypes.Structure): +class JrtcAppCfg_t(Structure): _fields_ = [ ("context", c_char_p), ("q_size", c_int), ("num_streams", c_int), - ("streams", ctypes.POINTER(JrtcStreamCfg_t)), + ("streams", POINTER(JrtcStreamCfg_t)), ("initialization_timeout_secs", c_float), ("sleep_timeout_secs", c_float), - ("inactivity_timeout_secs", c_float) + ("inactivity_timeout_secs", c_float), ] -# Callback type definition for the handler function - -JrtcAppHandler = ctypes.CFUNCTYPE(None, c_bool, c_int, ctypes.POINTER(struct_jrtc_router_data_entry), c_void_p) - -# Function prototypes - -lib.jrtc_app_create.argtypes = [ctypes.POINTER(JrtcAppEnv), ctypes.POINTER(JrtcAppCfg_t), JrtcAppHandler, c_void_p] -lib.jrtc_app_create.restype = ctypes.POINTER(JrtcApp) +# Opaque types +class ChannelCtx(ctypes.Structure): pass +class RouterDataEntry(ctypes.Structure): pass -#lib.jrtc_app_destroy.argtypes = [c_void_p] -lib.jrtc_app_destroy.argtypes = [ctypes.POINTER(JrtcApp)] -lib.jrtc_app_destroy.restype = None - -lib.jrtc_app_run.argtypes = [ctypes.POINTER(JrtcApp)] -lib.jrtc_app_run.restype = None - -lib.jrtc_app_router_channel_send_input_msg.argtypes = [ctypes.POINTER(JrtcApp), c_int, c_void_p, c_int] -lib.jrtc_app_router_channel_send_input_msg.restype = c_int - -lib.jrtc_app_router_channel_send_output_msg.argtypes = [ctypes.POINTER(JrtcApp), c_int, c_void_p, c_int] -lib.jrtc_app_router_channel_send_output_msg.restype = c_int +# Callback type definition +JrtcAppHandler = ctypes.CFUNCTYPE( + None, c_bool, c_int, POINTER(struct_jrtc_router_data_entry), c_void_p +) +class StreamItem(ctypes.Structure): + sid: Optional[JrtcRouterStreamId] = None + registered: bool = False + chan_ctx: Optional[ChannelCtx] = None +class AppStateVars(ctypes.Structure): + pass -####################################################################### -# Python wrapper to call jrtc_app_create C function -def jrtc_app_create(capsule, app_cfg: JrtcAppCfg_t, app_handler: JrtcAppHandler, app_state: Any) -> None : +class JrtcAppCStruct(Structure): + _fields_ = [ + ("env_ctx", JrtcAppEnv), + ("app_cfg", JrtcAppCfg_t), + ("app_handler", JrtcAppHandler), + ("app_state", ctypes.c_void_p), + ("last_received_time", ctypes.c_float), + ] +class JrtcApp: + def __init__(self, env_ctx, app_cfg, app_handler, app_state): + super().__init__() + self.c_struct = JrtcAppCStruct(env_ctx, app_cfg, app_handler, app_state, time.monotonic()) + self.stream_items: list[StreamItem] = [] + + def init(self) -> int: + start_time = time.monotonic() + self.last_received_time = start_time + + for i in range(self.c_struct.app_cfg.num_streams): + stream = self.c_struct.app_cfg.streams[i] + si = StreamItem() + si.sid = JrtcRouterStreamId() + + ## res = jrtc_router_generate_stream_id(&sid, s.sid.destination, s.sid.device_id, s.sid.stream_source, s.sid.io_map); + res = si.sid.generate_id( + stream.sid.destination, + stream.sid.device_id, + stream.sid.stream_source, + stream.sid.io_map, + ) + print(3) + if res != 1: + print(f"{self.c_struct.app_cfg.context}:: Failed to generate stream ID for stream {i}") + return -1 + si.sid = si.sid.convert_to_struct_jrtc_router_stream_id() + + if stream.appChannel: + si.chan_ctx = jrtc_router_channel_create( + self.c_struct.env_ctx.dapp_ctx, stream.appChannel, si.sid + ) + if not si.chan_ctx: + print(f"{self.c_struct.app_cfg.context}:: Failed to create channel for stream {i}") + return -1 + + if stream.is_rx: + if not jrtc_router_channel_register_stream_id_req(self.c_struct.env_ctx.dapp_ctx, si.sid): + print(f"{self.c_struct.app_cfg.context}:: Failed to register stream {i}") + return -1 + si.registered = True + + self.stream_items.append(si) + + if self.c_struct.app_cfg.initialization_timeout_secs > 0: + if time.monotonic() - start_time > self.c_struct.app_cfg.initialization_timeout_secs: + print(f"{self.c_struct.app_cfg.context}:: Initialization timeout") + return -1 + + for i in range(self.c_struct.app_cfg.num_streams): + stream = self.c_struct.app_cfg.streams[i] + si = self.stream_items[i] + if not stream.is_rx and not si.chan_ctx: + k = 0 + while not jrtc_router_input_channel_exists(si.sid): + time.sleep(0.1) + if k == 10: + print(f"{self.c_struct.app_cfg.context}:: Waiting for creation of stream {i}") + k = 0 + else: + k += 1 + + if self.c_struct.app_cfg.initialization_timeout_secs > 0: + if time.monotonic() - start_time > self.c_struct.app_cfg.initialization_timeout_secs: + print(f"{self.c_struct.app_cfg.context}:: Timeout waiting for stream {i}") + return -1 + return 0 + + def cleanup(self): + print(f"{self.c_struct.app_cfg.context}:: Cleaning up app") + for si in self.stream_items: + if si.registered: + jrtc_router_channel_deregister_stream_id_req(self.c_struct.env_ctx.dapp_ctx, si.sid) + if si.chan_ctx: + jrtc_router_channel_destroy(si.chan_ctx) + + def run(self): + if self.init() != 0: + return + + data_entries = get_data_entry_array_ptr(self.c_struct.app_cfg.q_size) + while not self.c_struct.env_ctx.app_exit: + now = time.monotonic() + if ( + self.c_struct.app_cfg.inactivity_timeout_secs > 0 + and now - self.c_struct.last_received_time > self.c_struct.app_cfg.inactivity_timeout_secs + ): + self.c_struct.app_handler(True, -1, None, self.c_struct.app_state) + self.last_received_time = now + + num_rcv = jrtc_router_receive(self.c_struct.env_ctx.dapp_ctx, data_entries, self.c_struct.app_cfg.q_size) + for i in range(num_rcv): + data_entry = data_entries[i] + if not data_entry: + continue + for sidx in range(self.c_struct.app_cfg.num_streams): + stream = self.c_struct.app_cfg.streams[sidx] + si = self.stream_items[sidx] + if stream.is_rx and jrtc_router_stream_id_matches_req(data_entry.stream_id, si.sid): + self.c_struct.app_handler(False, sidx, data_entry, self.c_struct.app_state) + break + jrtc_router_channel_release_buf(data_entry.data) + self.c_struct.last_received_time = time.monotonic() + + if self.c_struct.app_cfg.sleep_timeout_secs > 0: + time.sleep(max(self.c_struct.app_cfg.sleep_timeout_secs, 1e-9)) + + self.cleanup() + + def get_stream(self, stream_idx: int) -> Optional[JrtcRouterStreamId]: + if 0 <= stream_idx < len(self.stream_items): + return self.stream_items[stream_idx].sid + + def get_chan_ctx(self, stream_idx: int) -> Optional[ChannelCtx]: + if 0 <= stream_idx < len(self.stream_items): + return self.stream_items[stream_idx].chan_ctx + +def jrtc_app_create(capsule, app_cfg: JrtcAppCfg_t, app_handler: JrtcAppHandler, app_state): env_ctx = get_ctx_from_capsule(capsule) - app_handler_c = JrtcAppHandler(app_handler) - - print("app_handler_c = ", app_handler_c) - app_handler_raw = ctypes.cast(app_handler_c, ctypes.c_void_p) - - return lib.jrtc_app_create( - ctypes.byref(env_ctx), - ctypes.byref(app_cfg), - app_handler_c, - ctypes.pointer(app_state)) - - -####################################################################### -# Python wrapper to call jrtc_app_run C function -def jrtc_app_run(app: ctypes.POINTER(JrtcApp)) -> None: - lib.jrtc_app_run(app) - - -####################################################################### -# Python wrapper to call jrtc_app_destroy -def jrtc_app_destroy(app: ctypes.POINTER(JrtcApp)) -> None: - lib.jrtc_app_destroy(app) - - -####################################################################### -# Python wrapper to call jrtc_router_channel_send_input_msg -def jrtc_app_router_channel_send_input_msg(app: ctypes.POINTER(JrtcApp), stream_idx: int, data: bytes, data_len: int) -> int: - return lib.jrtc_app_router_channel_send_input_msg(app, stream_idx, data, data_len) - - -####################################################################### -# Python wrapper to call jrtc_router_channel_send_input_msg -def jrtc_app_router_channel_send_output_msg(app: ctypes.POINTER(JrtcApp), stream_idx: int, data: bytes, data_len: int) -> int: - return lib.jrtc_app_router_channel_send_output_msg(app, stream_idx, data, data_len) - - - - - -######################################################## -# Lists of items to expose when this module is importd -######################################################## -__all__ = [ - 'JRTC_ROUTER_REQ_DEST_ANY', - 'JRTC_ROUTER_REQ_DEVICE_ID_ANY', - 'JRTC_ROUTER_REQ_DEST_NONE', - 'JRTC_ROUTER_REQ_STREAM_PATH_ANY', - 'JRTC_ROUTER_REQ_STREAM_NAME_ANY', - 'struct_jrtc_router_data_entry', - - 'JrtcStreamIdCfg_t', - 'JrtcAppChannelCfg_t', - 'JrtcStreamCfg_t', - 'JrtcAppCfg_t', - - 'JrtcApp', - 'jrtc_app_create', - 'jrtc_app_run', - 'jrtc_app_destroy', - 'jrtc_app_router_channel_send_input_msg', - 'jrtc_app_router_channel_send_output_msg', - - ] + app_handler_c = JrtcAppHandler(app_handler) + print(f"jrtc_app_create()") + app_instance = JrtcApp( + env_ctx=env_ctx, + app_cfg=app_cfg, + app_handler=app_handler_c, + app_state=ctypes.cast(ctypes.pointer(app_state), ctypes.c_void_p) + ) + #return ctypes.POINTER(JrtcApp)(app_instance) + return app_instance + +def jrtc_app_run(app) -> None: + app.run() + +def jrtc_app_destroy(app) -> None: + app.cleanup() + del app + +def jrtc_app_router_channel_send_input_msg(app: JrtcApp, stream_idx: int, data: bytes, data_len: int) -> int: + stream = app.get_stream(stream_idx) + if not stream: + return -1 + return jrtc_router_channel_send_input_msg(stream, data, data_len) + +def jrtc_app_router_channel_send_output_msg(app: JrtcApp, stream_idx: int, data: bytes, data_len: int) -> int: + chan_ctx = app.get_chan_ctx(stream_idx) + if not chan_ctx: + return -1 + return jrtc_router_channel_send_output_msg(chan_ctx, data, data_len) + +__all__ = [ + "JRTC_ROUTER_REQ_DEST_ANY", + "JRTC_ROUTER_REQ_DEVICE_ID_ANY", + "JRTC_ROUTER_REQ_DEST_NONE", + "JRTC_ROUTER_REQ_STREAM_PATH_ANY", + "JRTC_ROUTER_REQ_STREAM_NAME_ANY", + "struct_jrtc_router_data_entry", + "JrtcStreamIdCfg_t", + "JrtcAppChannelCfg_t", + "JrtcStreamCfg_t", + "JrtcAppCfg_t", + "JrtcApp", + "jrtc_app_create", + "jrtc_app_run", + "jrtc_app_destroy", + "jrtc_app_router_channel_send_input_msg", + "jrtc_app_router_channel_send_output_msg", +] diff --git a/src/wrapper_apis/python/jrtc_router_stream_id.py b/src/wrapper_apis/python/jrtc_router_stream_id.py index 6d0c3b22..02cdb26a 100644 --- a/src/wrapper_apis/python/jrtc_router_stream_id.py +++ b/src/wrapper_apis/python/jrtc_router_stream_id.py @@ -53,10 +53,10 @@ def generate_id(self, fwd_dst, device_id, stream_path, stream_name): b_stream_path = None b_stream_name = None if stream_path != None: - stream_path = stream_path.encode("utf-8") + #stream_path = stream_path.encode("utf-8") b_stream_path = ctypes.create_string_buffer(stream_path) if stream_name != None: - stream_name = stream_name.encode("utf-8") + #stream_name = stream_name.encode("utf-8") b_stream_name = ctypes.create_string_buffer(stream_name) res = stream_id_lib.jrtc_router_generate_stream_id( From 0099abf76ebf0606234f224abe3488f24aa6c8e8 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 12:40:19 +0100 Subject: [PATCH 07/20] Cleaup --- .../advanced_example_py/advanced_example1.py | 9 +- .../advanced_example_py/advanced_example2.py | 9 +- sample_apps/first_example_py/first_example.py | 8 - .../data_generator/generated_data.py | 882 -------------- .../generated_data_pb.py | 1012 ----------------- .../simple_input/simple_input.py | 882 -------------- .../simple_input_protobuf/simple_input_pb.py | 1012 ----------------- setup_jrtc_env.sh | 1 - .../python/jrtc_router_stream_id.py | 2 - 9 files changed, 2 insertions(+), 3815 deletions(-) delete mode 100644 sample_apps/jbpf_codelets/data_generator/generated_data.py delete mode 100644 sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py delete mode 100644 sample_apps/jbpf_codelets/simple_input/simple_input.py delete mode 100644 sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index 86348975..ad729f37 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -1,6 +1,5 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. -import json import os import sys import ctypes @@ -23,7 +22,7 @@ # Define the state variables for the application class AppStateVars(ctypes.Structure): _fields_ = [ - ("app", ctypes.POINTER(JrtcApp)), + ("app", ctypes.py_object), # add custom fields below ("agg_cnt", ctypes.c_int32) @@ -49,17 +48,11 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents - output = { - "dummy": 0, - "timestamp": 0, - "stream_idx": stream_idx, - } print("BEFORE") a = 10000 * [0] for i in range(10000): a[i] = 100 * [1] print("AFTER") - print(f"Testing json.dumps: {json.dumps(output, indent=2)}") if stream_idx == GENERATOR_OUT_STREAM_IDX: # Extract data from the received entry diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index ec98bf89..12f35dd7 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -1,6 +1,5 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. -import json import os import sys import ctypes @@ -23,7 +22,7 @@ # Define the state variables for the application class AppStateVars(ctypes.Structure): _fields_ = [ - ("app", ctypes.POINTER(JrtcApp)), + ("app", ctypes.py_object), # add custom fields below ("agg_cnt", ctypes.c_int32), @@ -47,17 +46,11 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents - output = { - "dummy": 0, - "timestamp": 0, - "stream_idx": stream_idx, - } print("BEFORE") a = 10000 * [0] for i in range(10000): a[i] = 100 * [1] print("AFTER") - print(f"Testing json.dumps: {json.dumps(output, indent=2)}") if stream_idx == GENERATOR_PB_OUT_STREAM_IDX: diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index a0f1b1f4..a4bcb2ae 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -1,6 +1,5 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. -import json import os import sys import ctypes @@ -47,17 +46,11 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents - output = { - "dummy": 0, - "timestamp": 0, - "stream_idx": stream_idx, - } print("BEFORE") a = 10000 * [0] for i in range(10000): a[i] = 100 * [1] print("AFTER") - print(f"Testing json.dumps: {json.dumps(output, indent=2)}") if stream_idx == GENERATOR_OUT_STREAM_IDX: @@ -128,7 +121,6 @@ def jrtc_start_app(capsule): state.app = jrtc_app_create(capsule, app_cfg, app_handler, state) # run the app - This is blocking until the app exists - print(f"type(state.app) = {type(state.app)}") jrtc_app_run(state.app) # clean up app resources diff --git a/sample_apps/jbpf_codelets/data_generator/generated_data.py b/sample_apps/jbpf_codelets/data_generator/generated_data.py deleted file mode 100644 index 6b016f84..00000000 --- a/sample_apps/jbpf_codelets/data_generator/generated_data.py +++ /dev/null @@ -1,882 +0,0 @@ -r"""Wrapper for generated_data.h - -Generated with: -/usr/local/bin/ctypesgen generated_data.h -o generated_data.py - -Do not modify this file. -""" - -__docformat__ = "restructuredtext" - -# Begin preamble for Python - -import ctypes -import sys -from ctypes import * # noqa: F401, F403 - -_int_types = (ctypes.c_int16, ctypes.c_int32) -if hasattr(ctypes, "c_int64"): - # Some builds of ctypes apparently do not have ctypes.c_int64 - # defined; it's a pretty good bet that these builds do not - # have 64-bit pointers. - _int_types += (ctypes.c_int64,) -for t in _int_types: - if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): - c_ptrdiff_t = t -del t -del _int_types - - - -class UserString: - def __init__(self, seq): - if isinstance(seq, bytes): - self.data = seq - elif isinstance(seq, UserString): - self.data = seq.data[:] - else: - self.data = str(seq).encode() - - def __bytes__(self): - return self.data - - def __str__(self): - return self.data.decode() - - def __repr__(self): - return repr(self.data) - - def __int__(self): - return int(self.data.decode()) - - def __long__(self): - return int(self.data.decode()) - - def __float__(self): - return float(self.data.decode()) - - def __complex__(self): - return complex(self.data.decode()) - - def __hash__(self): - return hash(self.data) - - def __le__(self, string): - if isinstance(string, UserString): - return self.data <= string.data - else: - return self.data <= string - - def __lt__(self, string): - if isinstance(string, UserString): - return self.data < string.data - else: - return self.data < string - - def __ge__(self, string): - if isinstance(string, UserString): - return self.data >= string.data - else: - return self.data >= string - - def __gt__(self, string): - if isinstance(string, UserString): - return self.data > string.data - else: - return self.data > string - - def __eq__(self, string): - if isinstance(string, UserString): - return self.data == string.data - else: - return self.data == string - - def __ne__(self, string): - if isinstance(string, UserString): - return self.data != string.data - else: - return self.data != string - - def __contains__(self, char): - return char in self.data - - def __len__(self): - return len(self.data) - - def __getitem__(self, index): - return self.__class__(self.data[index]) - - def __getslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - return self.__class__(self.data[start:end]) - - def __add__(self, other): - if isinstance(other, UserString): - return self.__class__(self.data + other.data) - elif isinstance(other, bytes): - return self.__class__(self.data + other) - else: - return self.__class__(self.data + str(other).encode()) - - def __radd__(self, other): - if isinstance(other, bytes): - return self.__class__(other + self.data) - else: - return self.__class__(str(other).encode() + self.data) - - def __mul__(self, n): - return self.__class__(self.data * n) - - __rmul__ = __mul__ - - def __mod__(self, args): - return self.__class__(self.data % args) - - # the following methods are defined in alphabetical order: - def capitalize(self): - return self.__class__(self.data.capitalize()) - - def center(self, width, *args): - return self.__class__(self.data.center(width, *args)) - - def count(self, sub, start=0, end=sys.maxsize): - return self.data.count(sub, start, end) - - def decode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.decode(encoding, errors)) - else: - return self.__class__(self.data.decode(encoding)) - else: - return self.__class__(self.data.decode()) - - def encode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.encode(encoding, errors)) - else: - return self.__class__(self.data.encode(encoding)) - else: - return self.__class__(self.data.encode()) - - def endswith(self, suffix, start=0, end=sys.maxsize): - return self.data.endswith(suffix, start, end) - - def expandtabs(self, tabsize=8): - return self.__class__(self.data.expandtabs(tabsize)) - - def find(self, sub, start=0, end=sys.maxsize): - return self.data.find(sub, start, end) - - def index(self, sub, start=0, end=sys.maxsize): - return self.data.index(sub, start, end) - - def isalpha(self): - return self.data.isalpha() - - def isalnum(self): - return self.data.isalnum() - - def isdecimal(self): - return self.data.isdecimal() - - def isdigit(self): - return self.data.isdigit() - - def islower(self): - return self.data.islower() - - def isnumeric(self): - return self.data.isnumeric() - - def isspace(self): - return self.data.isspace() - - def istitle(self): - return self.data.istitle() - - def isupper(self): - return self.data.isupper() - - def join(self, seq): - return self.data.join(seq) - - def ljust(self, width, *args): - return self.__class__(self.data.ljust(width, *args)) - - def lower(self): - return self.__class__(self.data.lower()) - - def lstrip(self, chars=None): - return self.__class__(self.data.lstrip(chars)) - - def partition(self, sep): - return self.data.partition(sep) - - def replace(self, old, new, maxsplit=-1): - return self.__class__(self.data.replace(old, new, maxsplit)) - - def rfind(self, sub, start=0, end=sys.maxsize): - return self.data.rfind(sub, start, end) - - def rindex(self, sub, start=0, end=sys.maxsize): - return self.data.rindex(sub, start, end) - - def rjust(self, width, *args): - return self.__class__(self.data.rjust(width, *args)) - - def rpartition(self, sep): - return self.data.rpartition(sep) - - def rstrip(self, chars=None): - return self.__class__(self.data.rstrip(chars)) - - def split(self, sep=None, maxsplit=-1): - return self.data.split(sep, maxsplit) - - def rsplit(self, sep=None, maxsplit=-1): - return self.data.rsplit(sep, maxsplit) - - def splitlines(self, keepends=0): - return self.data.splitlines(keepends) - - def startswith(self, prefix, start=0, end=sys.maxsize): - return self.data.startswith(prefix, start, end) - - def strip(self, chars=None): - return self.__class__(self.data.strip(chars)) - - def swapcase(self): - return self.__class__(self.data.swapcase()) - - def title(self): - return self.__class__(self.data.title()) - - def translate(self, *args): - return self.__class__(self.data.translate(*args)) - - def upper(self): - return self.__class__(self.data.upper()) - - def zfill(self, width): - return self.__class__(self.data.zfill(width)) - - -class MutableString(UserString): - """mutable string objects - - Python strings are immutable objects. This has the advantage, that - strings may be used as dictionary keys. If this property isn't needed - and you insist on changing string values in place instead, you may cheat - and use MutableString. - - But the purpose of this class is an educational one: to prevent - people from inventing their own mutable string class derived - from UserString and than forget thereby to remove (override) the - __hash__ method inherited from UserString. This would lead to - errors that would be very hard to track down. - - A faster and better solution is to rewrite your program using lists.""" - - def __init__(self, string=""): - self.data = string - - def __hash__(self): - raise TypeError("unhashable type (it is mutable)") - - def __setitem__(self, index, sub): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + sub + self.data[index + 1 :] - - def __delitem__(self, index): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + self.data[index + 1 :] - - def __setslice__(self, start, end, sub): - start = max(start, 0) - end = max(end, 0) - if isinstance(sub, UserString): - self.data = self.data[:start] + sub.data + self.data[end:] - elif isinstance(sub, bytes): - self.data = self.data[:start] + sub + self.data[end:] - else: - self.data = self.data[:start] + str(sub).encode() + self.data[end:] - - def __delslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - self.data = self.data[:start] + self.data[end:] - - def immutable(self): - return UserString(self.data) - - def __iadd__(self, other): - if isinstance(other, UserString): - self.data += other.data - elif isinstance(other, bytes): - self.data += other - else: - self.data += str(other).encode() - return self - - def __imul__(self, n): - self.data *= n - return self - - -class String(MutableString, ctypes.Union): - - _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] - - def __init__(self, obj=b""): - if isinstance(obj, (bytes, UserString)): - self.data = bytes(obj) - else: - self.raw = obj - - def __len__(self): - return self.data and len(self.data) or 0 - - def from_param(cls, obj): - # Convert None or 0 - if obj is None or obj == 0: - return cls(ctypes.POINTER(ctypes.c_char)()) - - # Convert from String - elif isinstance(obj, String): - return obj - - # Convert from bytes - elif isinstance(obj, bytes): - return cls(obj) - - # Convert from str - elif isinstance(obj, str): - return cls(obj.encode()) - - # Convert from c_char_p - elif isinstance(obj, ctypes.c_char_p): - return obj - - # Convert from POINTER(ctypes.c_char) - elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): - return obj - - # Convert from raw pointer - elif isinstance(obj, int): - return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) - - # Convert from ctypes.c_char array - elif isinstance(obj, ctypes.c_char * len(obj)): - return obj - - # Convert from object - else: - return String.from_param(obj._as_parameter_) - - from_param = classmethod(from_param) - - -def ReturnString(obj, func=None, arguments=None): - return String.from_param(obj) - - -# As of ctypes 1.0, ctypes does not support custom error-checking -# functions on callbacks, nor does it support custom datatypes on -# callbacks, so we must ensure that all callbacks return -# primitive datatypes. -# -# Non-primitive return values wrapped with UNCHECKED won't be -# typechecked, and will be converted to ctypes.c_void_p. -def UNCHECKED(type): - if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": - return type - else: - return ctypes.c_void_p - - -# ctypes doesn't have direct support for variadic functions, so we have to write -# our own wrapper class -class _variadic_function(object): - def __init__(self, func, restype, argtypes, errcheck): - self.func = func - self.func.restype = restype - self.argtypes = argtypes - if errcheck: - self.func.errcheck = errcheck - - def _as_parameter_(self): - # So we can pass this variadic function as a function pointer - return self.func - - def __call__(self, *args): - fixed_args = [] - i = 0 - for argtype in self.argtypes: - # Typecheck what we can - fixed_args.append(argtype.from_param(args[i])) - i += 1 - return self.func(*fixed_args + list(args[i:])) - - -def ord_if_char(value): - """ - Simple helper used for casts to simple builtin types: if the argument is a - string type, it will be converted to it's ordinal value. - - This function will raise an exception if the argument is string with more - than one characters. - """ - return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value - -# End preamble - -_libs = {} -_libdirs = [] - -# Begin loader - -""" -Load libraries - appropriately for all our supported platforms -""" -# ---------------------------------------------------------------------------- -# Copyright (c) 2008 David James -# Copyright (c) 2006-2008 Alex Holkner -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of pyglet nor the names of its -# contributors may be used to endorse or promote products -# derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# ---------------------------------------------------------------------------- - -import ctypes -import ctypes.util -import glob -import os.path -import platform -import re -import sys - - -def _environ_path(name): - """Split an environment variable into a path-like list elements""" - if name in os.environ: - return os.environ[name].split(":") - return [] - - -class LibraryLoader: - """ - A base class For loading of libraries ;-) - Subclasses load libraries for specific platforms. - """ - - # library names formatted specifically for platforms - name_formats = ["%s"] - - class Lookup: - """Looking up calling conventions for a platform""" - - mode = ctypes.DEFAULT_MODE - - def __init__(self, path): - super(LibraryLoader.Lookup, self).__init__() - self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) - - def get(self, name, calling_convention="cdecl"): - """Return the given name according to the selected calling convention""" - if calling_convention not in self.access: - raise LookupError( - "Unknown calling convention '{}' for function '{}'".format( - calling_convention, name - ) - ) - return getattr(self.access[calling_convention], name) - - def has(self, name, calling_convention="cdecl"): - """Return True if this given calling convention finds the given 'name'""" - if calling_convention not in self.access: - return False - return hasattr(self.access[calling_convention], name) - - def __getattr__(self, name): - return getattr(self.access["cdecl"], name) - - def __init__(self): - self.other_dirs = [] - - def __call__(self, libname): - """Given the name of a library, load it.""" - paths = self.getpaths(libname) - - for path in paths: - # noinspection PyBroadException - try: - return self.Lookup(path) - except Exception: # pylint: disable=broad-except - pass - - raise ImportError("Could not load %s." % libname) - - def getpaths(self, libname): - """Return a list of paths where the library might be found.""" - if os.path.isabs(libname): - yield libname - else: - # search through a prioritized series of locations for the library - - # we first search any specific directories identified by user - for dir_i in self.other_dirs: - for fmt in self.name_formats: - # dir_i should be absolute already - yield os.path.join(dir_i, fmt % libname) - - # check if this code is even stored in a physical file - try: - this_file = __file__ - except NameError: - this_file = None - - # then we search the directory where the generated python interface is stored - if this_file is not None: - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) - - # now, use the ctypes tools to try to find the library - for fmt in self.name_formats: - path = ctypes.util.find_library(fmt % libname) - if path: - yield path - - # then we search all paths identified as platform-specific lib paths - for path in self.getplatformpaths(libname): - yield path - - # Finally, we'll try the users current working directory - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) - - def getplatformpaths(self, _libname): # pylint: disable=no-self-use - """Return all the library paths available in this platform""" - return [] - - -# Darwin (Mac OS X) - - -class DarwinLibraryLoader(LibraryLoader): - """Library loader for MacOS""" - - name_formats = [ - "lib%s.dylib", - "lib%s.so", - "lib%s.bundle", - "%s.dylib", - "%s.so", - "%s.bundle", - "%s", - ] - - class Lookup(LibraryLoader.Lookup): - """ - Looking up library files for this platform (Darwin aka MacOS) - """ - - # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead - # of the default RTLD_LOCAL. Without this, you end up with - # libraries not being loadable, resulting in "Symbol not found" - # errors - mode = ctypes.RTLD_GLOBAL - - def getplatformpaths(self, libname): - if os.path.pathsep in libname: - names = [libname] - else: - names = [fmt % libname for fmt in self.name_formats] - - for directory in self.getdirs(libname): - for name in names: - yield os.path.join(directory, name) - - @staticmethod - def getdirs(libname): - """Implements the dylib search as specified in Apple documentation: - - http://developer.apple.com/documentation/DeveloperTools/Conceptual/ - DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html - - Before commencing the standard search, the method first checks - the bundle's ``Frameworks`` directory if the application is running - within a bundle (OS X .app). - """ - - dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") - if not dyld_fallback_library_path: - dyld_fallback_library_path = [ - os.path.expanduser("~/lib"), - "/usr/local/lib", - "/usr/lib", - ] - - dirs = [] - - if "/" in libname: - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - else: - dirs.extend(_environ_path("LD_LIBRARY_PATH")) - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - dirs.extend(_environ_path("LD_RUN_PATH")) - - if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": - dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) - - dirs.extend(dyld_fallback_library_path) - - return dirs - - -# Posix - - -class PosixLibraryLoader(LibraryLoader): - """Library loader for POSIX-like systems (including Linux)""" - - _ld_so_cache = None - - _include = re.compile(r"^\s*include\s+(?P.*)") - - name_formats = ["lib%s.so", "%s.so", "%s"] - - class _Directories(dict): - """Deal with directories""" - - def __init__(self): - dict.__init__(self) - self.order = 0 - - def add(self, directory): - """Add a directory to our current set of directories""" - if len(directory) > 1: - directory = directory.rstrip(os.path.sep) - # only adds and updates order if exists and not already in set - if not os.path.exists(directory): - return - order = self.setdefault(directory, self.order) - if order == self.order: - self.order += 1 - - def extend(self, directories): - """Add a list of directories to our set""" - for a_dir in directories: - self.add(a_dir) - - def ordered(self): - """Sort the list of directories""" - return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) - - def _get_ld_so_conf_dirs(self, conf, dirs): - """ - Recursive function to help parse all ld.so.conf files, including proper - handling of the `include` directive. - """ - - try: - with open(conf) as fileobj: - for dirname in fileobj: - dirname = dirname.strip() - if not dirname: - continue - - match = self._include.match(dirname) - if not match: - dirs.add(dirname) - else: - for dir2 in glob.glob(match.group("pattern")): - self._get_ld_so_conf_dirs(dir2, dirs) - except IOError: - pass - - def _create_ld_so_cache(self): - # Recreate search path followed by ld.so. This is going to be - # slow to build, and incorrect (ld.so uses ld.so.cache, which may - # not be up-to-date). Used only as fallback for distros without - # /sbin/ldconfig. - # - # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. - - directories = self._Directories() - for name in ( - "LD_LIBRARY_PATH", - "SHLIB_PATH", # HP-UX - "LIBPATH", # OS/2, AIX - "LIBRARY_PATH", # BE/OS - ): - if name in os.environ: - directories.extend(os.environ[name].split(os.pathsep)) - - self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) - - bitage = platform.architecture()[0] - - unix_lib_dirs_list = [] - if bitage.startswith("64"): - # prefer 64 bit if that is our arch - unix_lib_dirs_list += ["/lib64", "/usr/lib64"] - - # must include standard libs, since those paths are also used by 64 bit - # installs - unix_lib_dirs_list += ["/lib", "/usr/lib"] - if sys.platform.startswith("linux"): - # Try and support multiarch work in Ubuntu - # https://wiki.ubuntu.com/MultiarchSpec - if bitage.startswith("32"): - # Assume Intel/AMD x86 compat - unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] - elif bitage.startswith("64"): - # Assume Intel/AMD x86 compatible - unix_lib_dirs_list += [ - "/lib/x86_64-linux-gnu", - "/usr/lib/x86_64-linux-gnu", - ] - else: - # guess... - unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") - directories.extend(unix_lib_dirs_list) - - cache = {} - lib_re = re.compile(r"lib(.*)\.s[ol]") - # ext_re = re.compile(r"\.s[ol]$") - for our_dir in directories.ordered(): - try: - for path in glob.glob("%s/*.s[ol]*" % our_dir): - file = os.path.basename(path) - - # Index by filename - cache_i = cache.setdefault(file, set()) - cache_i.add(path) - - # Index by library name - match = lib_re.match(file) - if match: - library = match.group(1) - cache_i = cache.setdefault(library, set()) - cache_i.add(path) - except OSError: - pass - - self._ld_so_cache = cache - - def getplatformpaths(self, libname): - if self._ld_so_cache is None: - self._create_ld_so_cache() - - result = self._ld_so_cache.get(libname, set()) - for i in result: - # we iterate through all found paths for library, since we may have - # actually found multiple architectures or other library types that - # may not load - yield i - - -# Windows - - -class WindowsLibraryLoader(LibraryLoader): - """Library loader for Microsoft Windows""" - - name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] - - class Lookup(LibraryLoader.Lookup): - """Lookup class for Windows libraries...""" - - def __init__(self, path): - super(WindowsLibraryLoader.Lookup, self).__init__(path) - self.access["stdcall"] = ctypes.windll.LoadLibrary(path) - - -# Platform switching - -# If your value of sys.platform does not appear in this dict, please contact -# the Ctypesgen maintainers. - -loaderclass = { - "darwin": DarwinLibraryLoader, - "cygwin": WindowsLibraryLoader, - "win32": WindowsLibraryLoader, - "msys": WindowsLibraryLoader, -} - -load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() - - -def add_library_search_dirs(other_dirs): - """ - Add libraries to search paths. - If library paths are relative, convert them to absolute with respect to this - file's directory - """ - for path in other_dirs: - if not os.path.isabs(path): - path = os.path.abspath(path) - load_library.other_dirs.append(path) - - -del loaderclass - -# End loader - -add_library_search_dirs([]) - -# No libraries - -# No modules - -# /jrtc/sample_apps/jbpf_codelets/data_generator/generated_data.h: 7 -class struct_anon_1(Structure): - pass - -struct_anon_1.__slots__ = [ - 'cnt', -] -struct_anon_1._fields_ = [ - ('cnt', c_int), -] - -example_msg = struct_anon_1# /jrtc/sample_apps/jbpf_codelets/data_generator/generated_data.h: 7 - -# No inserted files - -# No prefix-stripping - diff --git a/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py b/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py deleted file mode 100644 index be33a5c0..00000000 --- a/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data_pb.py +++ /dev/null @@ -1,1012 +0,0 @@ -r"""Wrapper for generated_data.pb.h - -Generated with: -/usr/local/bin/ctypesgen -I/jrtc/jbpf-protobuf/3p/nanopb generated_data.pb.h -o generated_data_pb.py - -Do not modify this file. -""" - -__docformat__ = "restructuredtext" - -# Begin preamble for Python - -import ctypes -import sys -from ctypes import * # noqa: F401, F403 - -_int_types = (ctypes.c_int16, ctypes.c_int32) -if hasattr(ctypes, "c_int64"): - # Some builds of ctypes apparently do not have ctypes.c_int64 - # defined; it's a pretty good bet that these builds do not - # have 64-bit pointers. - _int_types += (ctypes.c_int64,) -for t in _int_types: - if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): - c_ptrdiff_t = t -del t -del _int_types - - - -class UserString: - def __init__(self, seq): - if isinstance(seq, bytes): - self.data = seq - elif isinstance(seq, UserString): - self.data = seq.data[:] - else: - self.data = str(seq).encode() - - def __bytes__(self): - return self.data - - def __str__(self): - return self.data.decode() - - def __repr__(self): - return repr(self.data) - - def __int__(self): - return int(self.data.decode()) - - def __long__(self): - return int(self.data.decode()) - - def __float__(self): - return float(self.data.decode()) - - def __complex__(self): - return complex(self.data.decode()) - - def __hash__(self): - return hash(self.data) - - def __le__(self, string): - if isinstance(string, UserString): - return self.data <= string.data - else: - return self.data <= string - - def __lt__(self, string): - if isinstance(string, UserString): - return self.data < string.data - else: - return self.data < string - - def __ge__(self, string): - if isinstance(string, UserString): - return self.data >= string.data - else: - return self.data >= string - - def __gt__(self, string): - if isinstance(string, UserString): - return self.data > string.data - else: - return self.data > string - - def __eq__(self, string): - if isinstance(string, UserString): - return self.data == string.data - else: - return self.data == string - - def __ne__(self, string): - if isinstance(string, UserString): - return self.data != string.data - else: - return self.data != string - - def __contains__(self, char): - return char in self.data - - def __len__(self): - return len(self.data) - - def __getitem__(self, index): - return self.__class__(self.data[index]) - - def __getslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - return self.__class__(self.data[start:end]) - - def __add__(self, other): - if isinstance(other, UserString): - return self.__class__(self.data + other.data) - elif isinstance(other, bytes): - return self.__class__(self.data + other) - else: - return self.__class__(self.data + str(other).encode()) - - def __radd__(self, other): - if isinstance(other, bytes): - return self.__class__(other + self.data) - else: - return self.__class__(str(other).encode() + self.data) - - def __mul__(self, n): - return self.__class__(self.data * n) - - __rmul__ = __mul__ - - def __mod__(self, args): - return self.__class__(self.data % args) - - # the following methods are defined in alphabetical order: - def capitalize(self): - return self.__class__(self.data.capitalize()) - - def center(self, width, *args): - return self.__class__(self.data.center(width, *args)) - - def count(self, sub, start=0, end=sys.maxsize): - return self.data.count(sub, start, end) - - def decode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.decode(encoding, errors)) - else: - return self.__class__(self.data.decode(encoding)) - else: - return self.__class__(self.data.decode()) - - def encode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.encode(encoding, errors)) - else: - return self.__class__(self.data.encode(encoding)) - else: - return self.__class__(self.data.encode()) - - def endswith(self, suffix, start=0, end=sys.maxsize): - return self.data.endswith(suffix, start, end) - - def expandtabs(self, tabsize=8): - return self.__class__(self.data.expandtabs(tabsize)) - - def find(self, sub, start=0, end=sys.maxsize): - return self.data.find(sub, start, end) - - def index(self, sub, start=0, end=sys.maxsize): - return self.data.index(sub, start, end) - - def isalpha(self): - return self.data.isalpha() - - def isalnum(self): - return self.data.isalnum() - - def isdecimal(self): - return self.data.isdecimal() - - def isdigit(self): - return self.data.isdigit() - - def islower(self): - return self.data.islower() - - def isnumeric(self): - return self.data.isnumeric() - - def isspace(self): - return self.data.isspace() - - def istitle(self): - return self.data.istitle() - - def isupper(self): - return self.data.isupper() - - def join(self, seq): - return self.data.join(seq) - - def ljust(self, width, *args): - return self.__class__(self.data.ljust(width, *args)) - - def lower(self): - return self.__class__(self.data.lower()) - - def lstrip(self, chars=None): - return self.__class__(self.data.lstrip(chars)) - - def partition(self, sep): - return self.data.partition(sep) - - def replace(self, old, new, maxsplit=-1): - return self.__class__(self.data.replace(old, new, maxsplit)) - - def rfind(self, sub, start=0, end=sys.maxsize): - return self.data.rfind(sub, start, end) - - def rindex(self, sub, start=0, end=sys.maxsize): - return self.data.rindex(sub, start, end) - - def rjust(self, width, *args): - return self.__class__(self.data.rjust(width, *args)) - - def rpartition(self, sep): - return self.data.rpartition(sep) - - def rstrip(self, chars=None): - return self.__class__(self.data.rstrip(chars)) - - def split(self, sep=None, maxsplit=-1): - return self.data.split(sep, maxsplit) - - def rsplit(self, sep=None, maxsplit=-1): - return self.data.rsplit(sep, maxsplit) - - def splitlines(self, keepends=0): - return self.data.splitlines(keepends) - - def startswith(self, prefix, start=0, end=sys.maxsize): - return self.data.startswith(prefix, start, end) - - def strip(self, chars=None): - return self.__class__(self.data.strip(chars)) - - def swapcase(self): - return self.__class__(self.data.swapcase()) - - def title(self): - return self.__class__(self.data.title()) - - def translate(self, *args): - return self.__class__(self.data.translate(*args)) - - def upper(self): - return self.__class__(self.data.upper()) - - def zfill(self, width): - return self.__class__(self.data.zfill(width)) - - -class MutableString(UserString): - """mutable string objects - - Python strings are immutable objects. This has the advantage, that - strings may be used as dictionary keys. If this property isn't needed - and you insist on changing string values in place instead, you may cheat - and use MutableString. - - But the purpose of this class is an educational one: to prevent - people from inventing their own mutable string class derived - from UserString and than forget thereby to remove (override) the - __hash__ method inherited from UserString. This would lead to - errors that would be very hard to track down. - - A faster and better solution is to rewrite your program using lists.""" - - def __init__(self, string=""): - self.data = string - - def __hash__(self): - raise TypeError("unhashable type (it is mutable)") - - def __setitem__(self, index, sub): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + sub + self.data[index + 1 :] - - def __delitem__(self, index): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + self.data[index + 1 :] - - def __setslice__(self, start, end, sub): - start = max(start, 0) - end = max(end, 0) - if isinstance(sub, UserString): - self.data = self.data[:start] + sub.data + self.data[end:] - elif isinstance(sub, bytes): - self.data = self.data[:start] + sub + self.data[end:] - else: - self.data = self.data[:start] + str(sub).encode() + self.data[end:] - - def __delslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - self.data = self.data[:start] + self.data[end:] - - def immutable(self): - return UserString(self.data) - - def __iadd__(self, other): - if isinstance(other, UserString): - self.data += other.data - elif isinstance(other, bytes): - self.data += other - else: - self.data += str(other).encode() - return self - - def __imul__(self, n): - self.data *= n - return self - - -class String(MutableString, ctypes.Union): - - _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] - - def __init__(self, obj=b""): - if isinstance(obj, (bytes, UserString)): - self.data = bytes(obj) - else: - self.raw = obj - - def __len__(self): - return self.data and len(self.data) or 0 - - def from_param(cls, obj): - # Convert None or 0 - if obj is None or obj == 0: - return cls(ctypes.POINTER(ctypes.c_char)()) - - # Convert from String - elif isinstance(obj, String): - return obj - - # Convert from bytes - elif isinstance(obj, bytes): - return cls(obj) - - # Convert from str - elif isinstance(obj, str): - return cls(obj.encode()) - - # Convert from c_char_p - elif isinstance(obj, ctypes.c_char_p): - return obj - - # Convert from POINTER(ctypes.c_char) - elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): - return obj - - # Convert from raw pointer - elif isinstance(obj, int): - return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) - - # Convert from ctypes.c_char array - elif isinstance(obj, ctypes.c_char * len(obj)): - return obj - - # Convert from object - else: - return String.from_param(obj._as_parameter_) - - from_param = classmethod(from_param) - - -def ReturnString(obj, func=None, arguments=None): - return String.from_param(obj) - - -# As of ctypes 1.0, ctypes does not support custom error-checking -# functions on callbacks, nor does it support custom datatypes on -# callbacks, so we must ensure that all callbacks return -# primitive datatypes. -# -# Non-primitive return values wrapped with UNCHECKED won't be -# typechecked, and will be converted to ctypes.c_void_p. -def UNCHECKED(type): - if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": - return type - else: - return ctypes.c_void_p - - -# ctypes doesn't have direct support for variadic functions, so we have to write -# our own wrapper class -class _variadic_function(object): - def __init__(self, func, restype, argtypes, errcheck): - self.func = func - self.func.restype = restype - self.argtypes = argtypes - if errcheck: - self.func.errcheck = errcheck - - def _as_parameter_(self): - # So we can pass this variadic function as a function pointer - return self.func - - def __call__(self, *args): - fixed_args = [] - i = 0 - for argtype in self.argtypes: - # Typecheck what we can - fixed_args.append(argtype.from_param(args[i])) - i += 1 - return self.func(*fixed_args + list(args[i:])) - - -def ord_if_char(value): - """ - Simple helper used for casts to simple builtin types: if the argument is a - string type, it will be converted to it's ordinal value. - - This function will raise an exception if the argument is string with more - than one characters. - """ - return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value - -# End preamble - -_libs = {} -_libdirs = [] - -# Begin loader - -""" -Load libraries - appropriately for all our supported platforms -""" -# ---------------------------------------------------------------------------- -# Copyright (c) 2008 David James -# Copyright (c) 2006-2008 Alex Holkner -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of pyglet nor the names of its -# contributors may be used to endorse or promote products -# derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# ---------------------------------------------------------------------------- - -import ctypes -import ctypes.util -import glob -import os.path -import platform -import re -import sys - - -def _environ_path(name): - """Split an environment variable into a path-like list elements""" - if name in os.environ: - return os.environ[name].split(":") - return [] - - -class LibraryLoader: - """ - A base class For loading of libraries ;-) - Subclasses load libraries for specific platforms. - """ - - # library names formatted specifically for platforms - name_formats = ["%s"] - - class Lookup: - """Looking up calling conventions for a platform""" - - mode = ctypes.DEFAULT_MODE - - def __init__(self, path): - super(LibraryLoader.Lookup, self).__init__() - self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) - - def get(self, name, calling_convention="cdecl"): - """Return the given name according to the selected calling convention""" - if calling_convention not in self.access: - raise LookupError( - "Unknown calling convention '{}' for function '{}'".format( - calling_convention, name - ) - ) - return getattr(self.access[calling_convention], name) - - def has(self, name, calling_convention="cdecl"): - """Return True if this given calling convention finds the given 'name'""" - if calling_convention not in self.access: - return False - return hasattr(self.access[calling_convention], name) - - def __getattr__(self, name): - return getattr(self.access["cdecl"], name) - - def __init__(self): - self.other_dirs = [] - - def __call__(self, libname): - """Given the name of a library, load it.""" - paths = self.getpaths(libname) - - for path in paths: - # noinspection PyBroadException - try: - return self.Lookup(path) - except Exception: # pylint: disable=broad-except - pass - - raise ImportError("Could not load %s." % libname) - - def getpaths(self, libname): - """Return a list of paths where the library might be found.""" - if os.path.isabs(libname): - yield libname - else: - # search through a prioritized series of locations for the library - - # we first search any specific directories identified by user - for dir_i in self.other_dirs: - for fmt in self.name_formats: - # dir_i should be absolute already - yield os.path.join(dir_i, fmt % libname) - - # check if this code is even stored in a physical file - try: - this_file = __file__ - except NameError: - this_file = None - - # then we search the directory where the generated python interface is stored - if this_file is not None: - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) - - # now, use the ctypes tools to try to find the library - for fmt in self.name_formats: - path = ctypes.util.find_library(fmt % libname) - if path: - yield path - - # then we search all paths identified as platform-specific lib paths - for path in self.getplatformpaths(libname): - yield path - - # Finally, we'll try the users current working directory - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) - - def getplatformpaths(self, _libname): # pylint: disable=no-self-use - """Return all the library paths available in this platform""" - return [] - - -# Darwin (Mac OS X) - - -class DarwinLibraryLoader(LibraryLoader): - """Library loader for MacOS""" - - name_formats = [ - "lib%s.dylib", - "lib%s.so", - "lib%s.bundle", - "%s.dylib", - "%s.so", - "%s.bundle", - "%s", - ] - - class Lookup(LibraryLoader.Lookup): - """ - Looking up library files for this platform (Darwin aka MacOS) - """ - - # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead - # of the default RTLD_LOCAL. Without this, you end up with - # libraries not being loadable, resulting in "Symbol not found" - # errors - mode = ctypes.RTLD_GLOBAL - - def getplatformpaths(self, libname): - if os.path.pathsep in libname: - names = [libname] - else: - names = [fmt % libname for fmt in self.name_formats] - - for directory in self.getdirs(libname): - for name in names: - yield os.path.join(directory, name) - - @staticmethod - def getdirs(libname): - """Implements the dylib search as specified in Apple documentation: - - http://developer.apple.com/documentation/DeveloperTools/Conceptual/ - DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html - - Before commencing the standard search, the method first checks - the bundle's ``Frameworks`` directory if the application is running - within a bundle (OS X .app). - """ - - dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") - if not dyld_fallback_library_path: - dyld_fallback_library_path = [ - os.path.expanduser("~/lib"), - "/usr/local/lib", - "/usr/lib", - ] - - dirs = [] - - if "/" in libname: - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - else: - dirs.extend(_environ_path("LD_LIBRARY_PATH")) - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - dirs.extend(_environ_path("LD_RUN_PATH")) - - if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": - dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) - - dirs.extend(dyld_fallback_library_path) - - return dirs - - -# Posix - - -class PosixLibraryLoader(LibraryLoader): - """Library loader for POSIX-like systems (including Linux)""" - - _ld_so_cache = None - - _include = re.compile(r"^\s*include\s+(?P.*)") - - name_formats = ["lib%s.so", "%s.so", "%s"] - - class _Directories(dict): - """Deal with directories""" - - def __init__(self): - dict.__init__(self) - self.order = 0 - - def add(self, directory): - """Add a directory to our current set of directories""" - if len(directory) > 1: - directory = directory.rstrip(os.path.sep) - # only adds and updates order if exists and not already in set - if not os.path.exists(directory): - return - order = self.setdefault(directory, self.order) - if order == self.order: - self.order += 1 - - def extend(self, directories): - """Add a list of directories to our set""" - for a_dir in directories: - self.add(a_dir) - - def ordered(self): - """Sort the list of directories""" - return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) - - def _get_ld_so_conf_dirs(self, conf, dirs): - """ - Recursive function to help parse all ld.so.conf files, including proper - handling of the `include` directive. - """ - - try: - with open(conf) as fileobj: - for dirname in fileobj: - dirname = dirname.strip() - if not dirname: - continue - - match = self._include.match(dirname) - if not match: - dirs.add(dirname) - else: - for dir2 in glob.glob(match.group("pattern")): - self._get_ld_so_conf_dirs(dir2, dirs) - except IOError: - pass - - def _create_ld_so_cache(self): - # Recreate search path followed by ld.so. This is going to be - # slow to build, and incorrect (ld.so uses ld.so.cache, which may - # not be up-to-date). Used only as fallback for distros without - # /sbin/ldconfig. - # - # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. - - directories = self._Directories() - for name in ( - "LD_LIBRARY_PATH", - "SHLIB_PATH", # HP-UX - "LIBPATH", # OS/2, AIX - "LIBRARY_PATH", # BE/OS - ): - if name in os.environ: - directories.extend(os.environ[name].split(os.pathsep)) - - self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) - - bitage = platform.architecture()[0] - - unix_lib_dirs_list = [] - if bitage.startswith("64"): - # prefer 64 bit if that is our arch - unix_lib_dirs_list += ["/lib64", "/usr/lib64"] - - # must include standard libs, since those paths are also used by 64 bit - # installs - unix_lib_dirs_list += ["/lib", "/usr/lib"] - if sys.platform.startswith("linux"): - # Try and support multiarch work in Ubuntu - # https://wiki.ubuntu.com/MultiarchSpec - if bitage.startswith("32"): - # Assume Intel/AMD x86 compat - unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] - elif bitage.startswith("64"): - # Assume Intel/AMD x86 compatible - unix_lib_dirs_list += [ - "/lib/x86_64-linux-gnu", - "/usr/lib/x86_64-linux-gnu", - ] - else: - # guess... - unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") - directories.extend(unix_lib_dirs_list) - - cache = {} - lib_re = re.compile(r"lib(.*)\.s[ol]") - # ext_re = re.compile(r"\.s[ol]$") - for our_dir in directories.ordered(): - try: - for path in glob.glob("%s/*.s[ol]*" % our_dir): - file = os.path.basename(path) - - # Index by filename - cache_i = cache.setdefault(file, set()) - cache_i.add(path) - - # Index by library name - match = lib_re.match(file) - if match: - library = match.group(1) - cache_i = cache.setdefault(library, set()) - cache_i.add(path) - except OSError: - pass - - self._ld_so_cache = cache - - def getplatformpaths(self, libname): - if self._ld_so_cache is None: - self._create_ld_so_cache() - - result = self._ld_so_cache.get(libname, set()) - for i in result: - # we iterate through all found paths for library, since we may have - # actually found multiple architectures or other library types that - # may not load - yield i - - -# Windows - - -class WindowsLibraryLoader(LibraryLoader): - """Library loader for Microsoft Windows""" - - name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] - - class Lookup(LibraryLoader.Lookup): - """Lookup class for Windows libraries...""" - - def __init__(self, path): - super(WindowsLibraryLoader.Lookup, self).__init__(path) - self.access["stdcall"] = ctypes.windll.LoadLibrary(path) - - -# Platform switching - -# If your value of sys.platform does not appear in this dict, please contact -# the Ctypesgen maintainers. - -loaderclass = { - "darwin": DarwinLibraryLoader, - "cygwin": WindowsLibraryLoader, - "win32": WindowsLibraryLoader, - "msys": WindowsLibraryLoader, -} - -load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() - - -def add_library_search_dirs(other_dirs): - """ - Add libraries to search paths. - If library paths are relative, convert them to absolute with respect to this - file's directory - """ - for path in other_dirs: - if not os.path.isabs(path): - path = os.path.abspath(path) - load_library.other_dirs.append(path) - - -del loaderclass - -# End loader - -add_library_search_dirs([]) - -# No libraries - -# No modules - -__uint8_t = c_ubyte# /usr/include/x86_64-linux-gnu/bits/types.h: 38 - -__uint16_t = c_ushort# /usr/include/x86_64-linux-gnu/bits/types.h: 40 - -__uint32_t = c_uint# /usr/include/x86_64-linux-gnu/bits/types.h: 42 - -__uint_least16_t = __uint16_t# /usr/include/x86_64-linux-gnu/bits/types.h: 55 - -uint8_t = __uint8_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 24 - -uint32_t = __uint32_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 26 - -uint_least16_t = __uint_least16_t# /usr/include/stdint.h: 50 - -pb_byte_t = uint8_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 241 - -pb_type_t = pb_byte_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 250 - -pb_size_t = uint_least16_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 326 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 -class struct_pb_istream_s(Structure): - pass - -pb_istream_t = struct_pb_istream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 -class struct_pb_ostream_s(Structure): - pass - -pb_ostream_t = struct_pb_ostream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 353 -class struct_pb_field_iter_s(Structure): - pass - -pb_field_iter_t = struct_pb_field_iter_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 334 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 340 -class struct_pb_msgdesc_s(Structure): - pass - -pb_msgdesc_t = struct_pb_msgdesc_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 339 - -struct_pb_msgdesc_s.__slots__ = [ - 'field_info', - 'submsg_info', - 'default_value', - 'field_callback', - 'field_count', - 'required_field_count', - 'largest_tag', -] -struct_pb_msgdesc_s._fields_ = [ - ('field_info', POINTER(uint32_t)), - ('submsg_info', POINTER(POINTER(pb_msgdesc_t))), - ('default_value', POINTER(pb_byte_t)), - ('field_callback', CFUNCTYPE(UNCHECKED(c_bool), POINTER(pb_istream_t), POINTER(pb_ostream_t), POINTER(pb_field_iter_t))), - ('field_count', pb_size_t), - ('required_field_count', pb_size_t), - ('largest_tag', pb_size_t), -] - -struct_pb_field_iter_s.__slots__ = [ - 'descriptor', - 'message', - 'index', - 'field_info_index', - 'required_field_index', - 'submessage_index', - 'tag', - 'data_size', - 'array_size', - 'type', - 'pField', - 'pData', - 'pSize', - 'submsg_desc', -] -struct_pb_field_iter_s._fields_ = [ - ('descriptor', POINTER(pb_msgdesc_t)), - ('message', POINTER(None)), - ('index', pb_size_t), - ('field_info_index', pb_size_t), - ('required_field_index', pb_size_t), - ('submessage_index', pb_size_t), - ('tag', pb_size_t), - ('data_size', pb_size_t), - ('array_size', pb_size_t), - ('type', pb_type_t), - ('pField', POINTER(None)), - ('pData', POINTER(None)), - ('pSize', POINTER(None)), - ('submsg_desc', POINTER(pb_msgdesc_t)), -] - -# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 15 -class struct__example_msg_pb(Structure): - pass - -struct__example_msg_pb.__slots__ = [ - 'cnt', -] -struct__example_msg_pb._fields_ = [ - ('cnt', uint32_t), -] - -example_msg_pb = struct__example_msg_pb# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 15 - -# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 35 -for _lib in _libs.values(): - try: - example_msg_pb_msg = (pb_msgdesc_t).in_dll(_lib, "example_msg_pb_msg") - break - except: - pass - -# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 27 -try: - example_msg_pb_cnt_tag = 1 -except: - pass - -# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 38 -try: - example_msg_pb_fields = pointer(example_msg_pb_msg) -except: - pass - -# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 41 -try: - GENERATED_DATA_PB_H_MAX_SIZE = example_msg_pb_size -except: - pass - -# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 42 -try: - example_msg_pb_size = 6 -except: - pass - -_example_msg_pb = struct__example_msg_pb# /jrtc/sample_apps/jbpf_codelets/data_generator_protobuf/generated_data.pb.h: 15 - -# No inserted files - -# No prefix-stripping - diff --git a/sample_apps/jbpf_codelets/simple_input/simple_input.py b/sample_apps/jbpf_codelets/simple_input/simple_input.py deleted file mode 100644 index 10c49cb7..00000000 --- a/sample_apps/jbpf_codelets/simple_input/simple_input.py +++ /dev/null @@ -1,882 +0,0 @@ -r"""Wrapper for simple_input.h - -Generated with: -/usr/local/bin/ctypesgen simple_input.h -o simple_input.py - -Do not modify this file. -""" - -__docformat__ = "restructuredtext" - -# Begin preamble for Python - -import ctypes -import sys -from ctypes import * # noqa: F401, F403 - -_int_types = (ctypes.c_int16, ctypes.c_int32) -if hasattr(ctypes, "c_int64"): - # Some builds of ctypes apparently do not have ctypes.c_int64 - # defined; it's a pretty good bet that these builds do not - # have 64-bit pointers. - _int_types += (ctypes.c_int64,) -for t in _int_types: - if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): - c_ptrdiff_t = t -del t -del _int_types - - - -class UserString: - def __init__(self, seq): - if isinstance(seq, bytes): - self.data = seq - elif isinstance(seq, UserString): - self.data = seq.data[:] - else: - self.data = str(seq).encode() - - def __bytes__(self): - return self.data - - def __str__(self): - return self.data.decode() - - def __repr__(self): - return repr(self.data) - - def __int__(self): - return int(self.data.decode()) - - def __long__(self): - return int(self.data.decode()) - - def __float__(self): - return float(self.data.decode()) - - def __complex__(self): - return complex(self.data.decode()) - - def __hash__(self): - return hash(self.data) - - def __le__(self, string): - if isinstance(string, UserString): - return self.data <= string.data - else: - return self.data <= string - - def __lt__(self, string): - if isinstance(string, UserString): - return self.data < string.data - else: - return self.data < string - - def __ge__(self, string): - if isinstance(string, UserString): - return self.data >= string.data - else: - return self.data >= string - - def __gt__(self, string): - if isinstance(string, UserString): - return self.data > string.data - else: - return self.data > string - - def __eq__(self, string): - if isinstance(string, UserString): - return self.data == string.data - else: - return self.data == string - - def __ne__(self, string): - if isinstance(string, UserString): - return self.data != string.data - else: - return self.data != string - - def __contains__(self, char): - return char in self.data - - def __len__(self): - return len(self.data) - - def __getitem__(self, index): - return self.__class__(self.data[index]) - - def __getslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - return self.__class__(self.data[start:end]) - - def __add__(self, other): - if isinstance(other, UserString): - return self.__class__(self.data + other.data) - elif isinstance(other, bytes): - return self.__class__(self.data + other) - else: - return self.__class__(self.data + str(other).encode()) - - def __radd__(self, other): - if isinstance(other, bytes): - return self.__class__(other + self.data) - else: - return self.__class__(str(other).encode() + self.data) - - def __mul__(self, n): - return self.__class__(self.data * n) - - __rmul__ = __mul__ - - def __mod__(self, args): - return self.__class__(self.data % args) - - # the following methods are defined in alphabetical order: - def capitalize(self): - return self.__class__(self.data.capitalize()) - - def center(self, width, *args): - return self.__class__(self.data.center(width, *args)) - - def count(self, sub, start=0, end=sys.maxsize): - return self.data.count(sub, start, end) - - def decode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.decode(encoding, errors)) - else: - return self.__class__(self.data.decode(encoding)) - else: - return self.__class__(self.data.decode()) - - def encode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.encode(encoding, errors)) - else: - return self.__class__(self.data.encode(encoding)) - else: - return self.__class__(self.data.encode()) - - def endswith(self, suffix, start=0, end=sys.maxsize): - return self.data.endswith(suffix, start, end) - - def expandtabs(self, tabsize=8): - return self.__class__(self.data.expandtabs(tabsize)) - - def find(self, sub, start=0, end=sys.maxsize): - return self.data.find(sub, start, end) - - def index(self, sub, start=0, end=sys.maxsize): - return self.data.index(sub, start, end) - - def isalpha(self): - return self.data.isalpha() - - def isalnum(self): - return self.data.isalnum() - - def isdecimal(self): - return self.data.isdecimal() - - def isdigit(self): - return self.data.isdigit() - - def islower(self): - return self.data.islower() - - def isnumeric(self): - return self.data.isnumeric() - - def isspace(self): - return self.data.isspace() - - def istitle(self): - return self.data.istitle() - - def isupper(self): - return self.data.isupper() - - def join(self, seq): - return self.data.join(seq) - - def ljust(self, width, *args): - return self.__class__(self.data.ljust(width, *args)) - - def lower(self): - return self.__class__(self.data.lower()) - - def lstrip(self, chars=None): - return self.__class__(self.data.lstrip(chars)) - - def partition(self, sep): - return self.data.partition(sep) - - def replace(self, old, new, maxsplit=-1): - return self.__class__(self.data.replace(old, new, maxsplit)) - - def rfind(self, sub, start=0, end=sys.maxsize): - return self.data.rfind(sub, start, end) - - def rindex(self, sub, start=0, end=sys.maxsize): - return self.data.rindex(sub, start, end) - - def rjust(self, width, *args): - return self.__class__(self.data.rjust(width, *args)) - - def rpartition(self, sep): - return self.data.rpartition(sep) - - def rstrip(self, chars=None): - return self.__class__(self.data.rstrip(chars)) - - def split(self, sep=None, maxsplit=-1): - return self.data.split(sep, maxsplit) - - def rsplit(self, sep=None, maxsplit=-1): - return self.data.rsplit(sep, maxsplit) - - def splitlines(self, keepends=0): - return self.data.splitlines(keepends) - - def startswith(self, prefix, start=0, end=sys.maxsize): - return self.data.startswith(prefix, start, end) - - def strip(self, chars=None): - return self.__class__(self.data.strip(chars)) - - def swapcase(self): - return self.__class__(self.data.swapcase()) - - def title(self): - return self.__class__(self.data.title()) - - def translate(self, *args): - return self.__class__(self.data.translate(*args)) - - def upper(self): - return self.__class__(self.data.upper()) - - def zfill(self, width): - return self.__class__(self.data.zfill(width)) - - -class MutableString(UserString): - """mutable string objects - - Python strings are immutable objects. This has the advantage, that - strings may be used as dictionary keys. If this property isn't needed - and you insist on changing string values in place instead, you may cheat - and use MutableString. - - But the purpose of this class is an educational one: to prevent - people from inventing their own mutable string class derived - from UserString and than forget thereby to remove (override) the - __hash__ method inherited from UserString. This would lead to - errors that would be very hard to track down. - - A faster and better solution is to rewrite your program using lists.""" - - def __init__(self, string=""): - self.data = string - - def __hash__(self): - raise TypeError("unhashable type (it is mutable)") - - def __setitem__(self, index, sub): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + sub + self.data[index + 1 :] - - def __delitem__(self, index): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + self.data[index + 1 :] - - def __setslice__(self, start, end, sub): - start = max(start, 0) - end = max(end, 0) - if isinstance(sub, UserString): - self.data = self.data[:start] + sub.data + self.data[end:] - elif isinstance(sub, bytes): - self.data = self.data[:start] + sub + self.data[end:] - else: - self.data = self.data[:start] + str(sub).encode() + self.data[end:] - - def __delslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - self.data = self.data[:start] + self.data[end:] - - def immutable(self): - return UserString(self.data) - - def __iadd__(self, other): - if isinstance(other, UserString): - self.data += other.data - elif isinstance(other, bytes): - self.data += other - else: - self.data += str(other).encode() - return self - - def __imul__(self, n): - self.data *= n - return self - - -class String(MutableString, ctypes.Union): - - _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] - - def __init__(self, obj=b""): - if isinstance(obj, (bytes, UserString)): - self.data = bytes(obj) - else: - self.raw = obj - - def __len__(self): - return self.data and len(self.data) or 0 - - def from_param(cls, obj): - # Convert None or 0 - if obj is None or obj == 0: - return cls(ctypes.POINTER(ctypes.c_char)()) - - # Convert from String - elif isinstance(obj, String): - return obj - - # Convert from bytes - elif isinstance(obj, bytes): - return cls(obj) - - # Convert from str - elif isinstance(obj, str): - return cls(obj.encode()) - - # Convert from c_char_p - elif isinstance(obj, ctypes.c_char_p): - return obj - - # Convert from POINTER(ctypes.c_char) - elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): - return obj - - # Convert from raw pointer - elif isinstance(obj, int): - return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) - - # Convert from ctypes.c_char array - elif isinstance(obj, ctypes.c_char * len(obj)): - return obj - - # Convert from object - else: - return String.from_param(obj._as_parameter_) - - from_param = classmethod(from_param) - - -def ReturnString(obj, func=None, arguments=None): - return String.from_param(obj) - - -# As of ctypes 1.0, ctypes does not support custom error-checking -# functions on callbacks, nor does it support custom datatypes on -# callbacks, so we must ensure that all callbacks return -# primitive datatypes. -# -# Non-primitive return values wrapped with UNCHECKED won't be -# typechecked, and will be converted to ctypes.c_void_p. -def UNCHECKED(type): - if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": - return type - else: - return ctypes.c_void_p - - -# ctypes doesn't have direct support for variadic functions, so we have to write -# our own wrapper class -class _variadic_function(object): - def __init__(self, func, restype, argtypes, errcheck): - self.func = func - self.func.restype = restype - self.argtypes = argtypes - if errcheck: - self.func.errcheck = errcheck - - def _as_parameter_(self): - # So we can pass this variadic function as a function pointer - return self.func - - def __call__(self, *args): - fixed_args = [] - i = 0 - for argtype in self.argtypes: - # Typecheck what we can - fixed_args.append(argtype.from_param(args[i])) - i += 1 - return self.func(*fixed_args + list(args[i:])) - - -def ord_if_char(value): - """ - Simple helper used for casts to simple builtin types: if the argument is a - string type, it will be converted to it's ordinal value. - - This function will raise an exception if the argument is string with more - than one characters. - """ - return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value - -# End preamble - -_libs = {} -_libdirs = [] - -# Begin loader - -""" -Load libraries - appropriately for all our supported platforms -""" -# ---------------------------------------------------------------------------- -# Copyright (c) 2008 David James -# Copyright (c) 2006-2008 Alex Holkner -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of pyglet nor the names of its -# contributors may be used to endorse or promote products -# derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# ---------------------------------------------------------------------------- - -import ctypes -import ctypes.util -import glob -import os.path -import platform -import re -import sys - - -def _environ_path(name): - """Split an environment variable into a path-like list elements""" - if name in os.environ: - return os.environ[name].split(":") - return [] - - -class LibraryLoader: - """ - A base class For loading of libraries ;-) - Subclasses load libraries for specific platforms. - """ - - # library names formatted specifically for platforms - name_formats = ["%s"] - - class Lookup: - """Looking up calling conventions for a platform""" - - mode = ctypes.DEFAULT_MODE - - def __init__(self, path): - super(LibraryLoader.Lookup, self).__init__() - self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) - - def get(self, name, calling_convention="cdecl"): - """Return the given name according to the selected calling convention""" - if calling_convention not in self.access: - raise LookupError( - "Unknown calling convention '{}' for function '{}'".format( - calling_convention, name - ) - ) - return getattr(self.access[calling_convention], name) - - def has(self, name, calling_convention="cdecl"): - """Return True if this given calling convention finds the given 'name'""" - if calling_convention not in self.access: - return False - return hasattr(self.access[calling_convention], name) - - def __getattr__(self, name): - return getattr(self.access["cdecl"], name) - - def __init__(self): - self.other_dirs = [] - - def __call__(self, libname): - """Given the name of a library, load it.""" - paths = self.getpaths(libname) - - for path in paths: - # noinspection PyBroadException - try: - return self.Lookup(path) - except Exception: # pylint: disable=broad-except - pass - - raise ImportError("Could not load %s." % libname) - - def getpaths(self, libname): - """Return a list of paths where the library might be found.""" - if os.path.isabs(libname): - yield libname - else: - # search through a prioritized series of locations for the library - - # we first search any specific directories identified by user - for dir_i in self.other_dirs: - for fmt in self.name_formats: - # dir_i should be absolute already - yield os.path.join(dir_i, fmt % libname) - - # check if this code is even stored in a physical file - try: - this_file = __file__ - except NameError: - this_file = None - - # then we search the directory where the generated python interface is stored - if this_file is not None: - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) - - # now, use the ctypes tools to try to find the library - for fmt in self.name_formats: - path = ctypes.util.find_library(fmt % libname) - if path: - yield path - - # then we search all paths identified as platform-specific lib paths - for path in self.getplatformpaths(libname): - yield path - - # Finally, we'll try the users current working directory - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) - - def getplatformpaths(self, _libname): # pylint: disable=no-self-use - """Return all the library paths available in this platform""" - return [] - - -# Darwin (Mac OS X) - - -class DarwinLibraryLoader(LibraryLoader): - """Library loader for MacOS""" - - name_formats = [ - "lib%s.dylib", - "lib%s.so", - "lib%s.bundle", - "%s.dylib", - "%s.so", - "%s.bundle", - "%s", - ] - - class Lookup(LibraryLoader.Lookup): - """ - Looking up library files for this platform (Darwin aka MacOS) - """ - - # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead - # of the default RTLD_LOCAL. Without this, you end up with - # libraries not being loadable, resulting in "Symbol not found" - # errors - mode = ctypes.RTLD_GLOBAL - - def getplatformpaths(self, libname): - if os.path.pathsep in libname: - names = [libname] - else: - names = [fmt % libname for fmt in self.name_formats] - - for directory in self.getdirs(libname): - for name in names: - yield os.path.join(directory, name) - - @staticmethod - def getdirs(libname): - """Implements the dylib search as specified in Apple documentation: - - http://developer.apple.com/documentation/DeveloperTools/Conceptual/ - DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html - - Before commencing the standard search, the method first checks - the bundle's ``Frameworks`` directory if the application is running - within a bundle (OS X .app). - """ - - dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") - if not dyld_fallback_library_path: - dyld_fallback_library_path = [ - os.path.expanduser("~/lib"), - "/usr/local/lib", - "/usr/lib", - ] - - dirs = [] - - if "/" in libname: - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - else: - dirs.extend(_environ_path("LD_LIBRARY_PATH")) - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - dirs.extend(_environ_path("LD_RUN_PATH")) - - if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": - dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) - - dirs.extend(dyld_fallback_library_path) - - return dirs - - -# Posix - - -class PosixLibraryLoader(LibraryLoader): - """Library loader for POSIX-like systems (including Linux)""" - - _ld_so_cache = None - - _include = re.compile(r"^\s*include\s+(?P.*)") - - name_formats = ["lib%s.so", "%s.so", "%s"] - - class _Directories(dict): - """Deal with directories""" - - def __init__(self): - dict.__init__(self) - self.order = 0 - - def add(self, directory): - """Add a directory to our current set of directories""" - if len(directory) > 1: - directory = directory.rstrip(os.path.sep) - # only adds and updates order if exists and not already in set - if not os.path.exists(directory): - return - order = self.setdefault(directory, self.order) - if order == self.order: - self.order += 1 - - def extend(self, directories): - """Add a list of directories to our set""" - for a_dir in directories: - self.add(a_dir) - - def ordered(self): - """Sort the list of directories""" - return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) - - def _get_ld_so_conf_dirs(self, conf, dirs): - """ - Recursive function to help parse all ld.so.conf files, including proper - handling of the `include` directive. - """ - - try: - with open(conf) as fileobj: - for dirname in fileobj: - dirname = dirname.strip() - if not dirname: - continue - - match = self._include.match(dirname) - if not match: - dirs.add(dirname) - else: - for dir2 in glob.glob(match.group("pattern")): - self._get_ld_so_conf_dirs(dir2, dirs) - except IOError: - pass - - def _create_ld_so_cache(self): - # Recreate search path followed by ld.so. This is going to be - # slow to build, and incorrect (ld.so uses ld.so.cache, which may - # not be up-to-date). Used only as fallback for distros without - # /sbin/ldconfig. - # - # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. - - directories = self._Directories() - for name in ( - "LD_LIBRARY_PATH", - "SHLIB_PATH", # HP-UX - "LIBPATH", # OS/2, AIX - "LIBRARY_PATH", # BE/OS - ): - if name in os.environ: - directories.extend(os.environ[name].split(os.pathsep)) - - self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) - - bitage = platform.architecture()[0] - - unix_lib_dirs_list = [] - if bitage.startswith("64"): - # prefer 64 bit if that is our arch - unix_lib_dirs_list += ["/lib64", "/usr/lib64"] - - # must include standard libs, since those paths are also used by 64 bit - # installs - unix_lib_dirs_list += ["/lib", "/usr/lib"] - if sys.platform.startswith("linux"): - # Try and support multiarch work in Ubuntu - # https://wiki.ubuntu.com/MultiarchSpec - if bitage.startswith("32"): - # Assume Intel/AMD x86 compat - unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] - elif bitage.startswith("64"): - # Assume Intel/AMD x86 compatible - unix_lib_dirs_list += [ - "/lib/x86_64-linux-gnu", - "/usr/lib/x86_64-linux-gnu", - ] - else: - # guess... - unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") - directories.extend(unix_lib_dirs_list) - - cache = {} - lib_re = re.compile(r"lib(.*)\.s[ol]") - # ext_re = re.compile(r"\.s[ol]$") - for our_dir in directories.ordered(): - try: - for path in glob.glob("%s/*.s[ol]*" % our_dir): - file = os.path.basename(path) - - # Index by filename - cache_i = cache.setdefault(file, set()) - cache_i.add(path) - - # Index by library name - match = lib_re.match(file) - if match: - library = match.group(1) - cache_i = cache.setdefault(library, set()) - cache_i.add(path) - except OSError: - pass - - self._ld_so_cache = cache - - def getplatformpaths(self, libname): - if self._ld_so_cache is None: - self._create_ld_so_cache() - - result = self._ld_so_cache.get(libname, set()) - for i in result: - # we iterate through all found paths for library, since we may have - # actually found multiple architectures or other library types that - # may not load - yield i - - -# Windows - - -class WindowsLibraryLoader(LibraryLoader): - """Library loader for Microsoft Windows""" - - name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] - - class Lookup(LibraryLoader.Lookup): - """Lookup class for Windows libraries...""" - - def __init__(self, path): - super(WindowsLibraryLoader.Lookup, self).__init__(path) - self.access["stdcall"] = ctypes.windll.LoadLibrary(path) - - -# Platform switching - -# If your value of sys.platform does not appear in this dict, please contact -# the Ctypesgen maintainers. - -loaderclass = { - "darwin": DarwinLibraryLoader, - "cygwin": WindowsLibraryLoader, - "win32": WindowsLibraryLoader, - "msys": WindowsLibraryLoader, -} - -load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() - - -def add_library_search_dirs(other_dirs): - """ - Add libraries to search paths. - If library paths are relative, convert them to absolute with respect to this - file's directory - """ - for path in other_dirs: - if not os.path.isabs(path): - path = os.path.abspath(path) - load_library.other_dirs.append(path) - - -del loaderclass - -# End loader - -add_library_search_dirs([]) - -# No libraries - -# No modules - -# /jrtc/sample_apps/jbpf_codelets/simple_input/simple_input.h: 7 -class struct_anon_1(Structure): - pass - -struct_anon_1.__slots__ = [ - 'aggregate_counter', -] -struct_anon_1._fields_ = [ - ('aggregate_counter', c_int), -] - -simple_input = struct_anon_1# /jrtc/sample_apps/jbpf_codelets/simple_input/simple_input.h: 7 - -# No inserted files - -# No prefix-stripping - diff --git a/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py b/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py deleted file mode 100644 index ce0e7170..00000000 --- a/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input_pb.py +++ /dev/null @@ -1,1012 +0,0 @@ -r"""Wrapper for simple_input.pb.h - -Generated with: -/usr/local/bin/ctypesgen -I/jrtc/jbpf-protobuf/3p/nanopb simple_input.pb.h -o simple_input_pb.py - -Do not modify this file. -""" - -__docformat__ = "restructuredtext" - -# Begin preamble for Python - -import ctypes -import sys -from ctypes import * # noqa: F401, F403 - -_int_types = (ctypes.c_int16, ctypes.c_int32) -if hasattr(ctypes, "c_int64"): - # Some builds of ctypes apparently do not have ctypes.c_int64 - # defined; it's a pretty good bet that these builds do not - # have 64-bit pointers. - _int_types += (ctypes.c_int64,) -for t in _int_types: - if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t): - c_ptrdiff_t = t -del t -del _int_types - - - -class UserString: - def __init__(self, seq): - if isinstance(seq, bytes): - self.data = seq - elif isinstance(seq, UserString): - self.data = seq.data[:] - else: - self.data = str(seq).encode() - - def __bytes__(self): - return self.data - - def __str__(self): - return self.data.decode() - - def __repr__(self): - return repr(self.data) - - def __int__(self): - return int(self.data.decode()) - - def __long__(self): - return int(self.data.decode()) - - def __float__(self): - return float(self.data.decode()) - - def __complex__(self): - return complex(self.data.decode()) - - def __hash__(self): - return hash(self.data) - - def __le__(self, string): - if isinstance(string, UserString): - return self.data <= string.data - else: - return self.data <= string - - def __lt__(self, string): - if isinstance(string, UserString): - return self.data < string.data - else: - return self.data < string - - def __ge__(self, string): - if isinstance(string, UserString): - return self.data >= string.data - else: - return self.data >= string - - def __gt__(self, string): - if isinstance(string, UserString): - return self.data > string.data - else: - return self.data > string - - def __eq__(self, string): - if isinstance(string, UserString): - return self.data == string.data - else: - return self.data == string - - def __ne__(self, string): - if isinstance(string, UserString): - return self.data != string.data - else: - return self.data != string - - def __contains__(self, char): - return char in self.data - - def __len__(self): - return len(self.data) - - def __getitem__(self, index): - return self.__class__(self.data[index]) - - def __getslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - return self.__class__(self.data[start:end]) - - def __add__(self, other): - if isinstance(other, UserString): - return self.__class__(self.data + other.data) - elif isinstance(other, bytes): - return self.__class__(self.data + other) - else: - return self.__class__(self.data + str(other).encode()) - - def __radd__(self, other): - if isinstance(other, bytes): - return self.__class__(other + self.data) - else: - return self.__class__(str(other).encode() + self.data) - - def __mul__(self, n): - return self.__class__(self.data * n) - - __rmul__ = __mul__ - - def __mod__(self, args): - return self.__class__(self.data % args) - - # the following methods are defined in alphabetical order: - def capitalize(self): - return self.__class__(self.data.capitalize()) - - def center(self, width, *args): - return self.__class__(self.data.center(width, *args)) - - def count(self, sub, start=0, end=sys.maxsize): - return self.data.count(sub, start, end) - - def decode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.decode(encoding, errors)) - else: - return self.__class__(self.data.decode(encoding)) - else: - return self.__class__(self.data.decode()) - - def encode(self, encoding=None, errors=None): # XXX improve this? - if encoding: - if errors: - return self.__class__(self.data.encode(encoding, errors)) - else: - return self.__class__(self.data.encode(encoding)) - else: - return self.__class__(self.data.encode()) - - def endswith(self, suffix, start=0, end=sys.maxsize): - return self.data.endswith(suffix, start, end) - - def expandtabs(self, tabsize=8): - return self.__class__(self.data.expandtabs(tabsize)) - - def find(self, sub, start=0, end=sys.maxsize): - return self.data.find(sub, start, end) - - def index(self, sub, start=0, end=sys.maxsize): - return self.data.index(sub, start, end) - - def isalpha(self): - return self.data.isalpha() - - def isalnum(self): - return self.data.isalnum() - - def isdecimal(self): - return self.data.isdecimal() - - def isdigit(self): - return self.data.isdigit() - - def islower(self): - return self.data.islower() - - def isnumeric(self): - return self.data.isnumeric() - - def isspace(self): - return self.data.isspace() - - def istitle(self): - return self.data.istitle() - - def isupper(self): - return self.data.isupper() - - def join(self, seq): - return self.data.join(seq) - - def ljust(self, width, *args): - return self.__class__(self.data.ljust(width, *args)) - - def lower(self): - return self.__class__(self.data.lower()) - - def lstrip(self, chars=None): - return self.__class__(self.data.lstrip(chars)) - - def partition(self, sep): - return self.data.partition(sep) - - def replace(self, old, new, maxsplit=-1): - return self.__class__(self.data.replace(old, new, maxsplit)) - - def rfind(self, sub, start=0, end=sys.maxsize): - return self.data.rfind(sub, start, end) - - def rindex(self, sub, start=0, end=sys.maxsize): - return self.data.rindex(sub, start, end) - - def rjust(self, width, *args): - return self.__class__(self.data.rjust(width, *args)) - - def rpartition(self, sep): - return self.data.rpartition(sep) - - def rstrip(self, chars=None): - return self.__class__(self.data.rstrip(chars)) - - def split(self, sep=None, maxsplit=-1): - return self.data.split(sep, maxsplit) - - def rsplit(self, sep=None, maxsplit=-1): - return self.data.rsplit(sep, maxsplit) - - def splitlines(self, keepends=0): - return self.data.splitlines(keepends) - - def startswith(self, prefix, start=0, end=sys.maxsize): - return self.data.startswith(prefix, start, end) - - def strip(self, chars=None): - return self.__class__(self.data.strip(chars)) - - def swapcase(self): - return self.__class__(self.data.swapcase()) - - def title(self): - return self.__class__(self.data.title()) - - def translate(self, *args): - return self.__class__(self.data.translate(*args)) - - def upper(self): - return self.__class__(self.data.upper()) - - def zfill(self, width): - return self.__class__(self.data.zfill(width)) - - -class MutableString(UserString): - """mutable string objects - - Python strings are immutable objects. This has the advantage, that - strings may be used as dictionary keys. If this property isn't needed - and you insist on changing string values in place instead, you may cheat - and use MutableString. - - But the purpose of this class is an educational one: to prevent - people from inventing their own mutable string class derived - from UserString and than forget thereby to remove (override) the - __hash__ method inherited from UserString. This would lead to - errors that would be very hard to track down. - - A faster and better solution is to rewrite your program using lists.""" - - def __init__(self, string=""): - self.data = string - - def __hash__(self): - raise TypeError("unhashable type (it is mutable)") - - def __setitem__(self, index, sub): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + sub + self.data[index + 1 :] - - def __delitem__(self, index): - if index < 0: - index += len(self.data) - if index < 0 or index >= len(self.data): - raise IndexError - self.data = self.data[:index] + self.data[index + 1 :] - - def __setslice__(self, start, end, sub): - start = max(start, 0) - end = max(end, 0) - if isinstance(sub, UserString): - self.data = self.data[:start] + sub.data + self.data[end:] - elif isinstance(sub, bytes): - self.data = self.data[:start] + sub + self.data[end:] - else: - self.data = self.data[:start] + str(sub).encode() + self.data[end:] - - def __delslice__(self, start, end): - start = max(start, 0) - end = max(end, 0) - self.data = self.data[:start] + self.data[end:] - - def immutable(self): - return UserString(self.data) - - def __iadd__(self, other): - if isinstance(other, UserString): - self.data += other.data - elif isinstance(other, bytes): - self.data += other - else: - self.data += str(other).encode() - return self - - def __imul__(self, n): - self.data *= n - return self - - -class String(MutableString, ctypes.Union): - - _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)] - - def __init__(self, obj=b""): - if isinstance(obj, (bytes, UserString)): - self.data = bytes(obj) - else: - self.raw = obj - - def __len__(self): - return self.data and len(self.data) or 0 - - def from_param(cls, obj): - # Convert None or 0 - if obj is None or obj == 0: - return cls(ctypes.POINTER(ctypes.c_char)()) - - # Convert from String - elif isinstance(obj, String): - return obj - - # Convert from bytes - elif isinstance(obj, bytes): - return cls(obj) - - # Convert from str - elif isinstance(obj, str): - return cls(obj.encode()) - - # Convert from c_char_p - elif isinstance(obj, ctypes.c_char_p): - return obj - - # Convert from POINTER(ctypes.c_char) - elif isinstance(obj, ctypes.POINTER(ctypes.c_char)): - return obj - - # Convert from raw pointer - elif isinstance(obj, int): - return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char))) - - # Convert from ctypes.c_char array - elif isinstance(obj, ctypes.c_char * len(obj)): - return obj - - # Convert from object - else: - return String.from_param(obj._as_parameter_) - - from_param = classmethod(from_param) - - -def ReturnString(obj, func=None, arguments=None): - return String.from_param(obj) - - -# As of ctypes 1.0, ctypes does not support custom error-checking -# functions on callbacks, nor does it support custom datatypes on -# callbacks, so we must ensure that all callbacks return -# primitive datatypes. -# -# Non-primitive return values wrapped with UNCHECKED won't be -# typechecked, and will be converted to ctypes.c_void_p. -def UNCHECKED(type): - if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P": - return type - else: - return ctypes.c_void_p - - -# ctypes doesn't have direct support for variadic functions, so we have to write -# our own wrapper class -class _variadic_function(object): - def __init__(self, func, restype, argtypes, errcheck): - self.func = func - self.func.restype = restype - self.argtypes = argtypes - if errcheck: - self.func.errcheck = errcheck - - def _as_parameter_(self): - # So we can pass this variadic function as a function pointer - return self.func - - def __call__(self, *args): - fixed_args = [] - i = 0 - for argtype in self.argtypes: - # Typecheck what we can - fixed_args.append(argtype.from_param(args[i])) - i += 1 - return self.func(*fixed_args + list(args[i:])) - - -def ord_if_char(value): - """ - Simple helper used for casts to simple builtin types: if the argument is a - string type, it will be converted to it's ordinal value. - - This function will raise an exception if the argument is string with more - than one characters. - """ - return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value - -# End preamble - -_libs = {} -_libdirs = [] - -# Begin loader - -""" -Load libraries - appropriately for all our supported platforms -""" -# ---------------------------------------------------------------------------- -# Copyright (c) 2008 David James -# Copyright (c) 2006-2008 Alex Holkner -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in -# the documentation and/or other materials provided with the -# distribution. -# * Neither the name of pyglet nor the names of its -# contributors may be used to endorse or promote products -# derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN -# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -# POSSIBILITY OF SUCH DAMAGE. -# ---------------------------------------------------------------------------- - -import ctypes -import ctypes.util -import glob -import os.path -import platform -import re -import sys - - -def _environ_path(name): - """Split an environment variable into a path-like list elements""" - if name in os.environ: - return os.environ[name].split(":") - return [] - - -class LibraryLoader: - """ - A base class For loading of libraries ;-) - Subclasses load libraries for specific platforms. - """ - - # library names formatted specifically for platforms - name_formats = ["%s"] - - class Lookup: - """Looking up calling conventions for a platform""" - - mode = ctypes.DEFAULT_MODE - - def __init__(self, path): - super(LibraryLoader.Lookup, self).__init__() - self.access = dict(cdecl=ctypes.CDLL(path, self.mode)) - - def get(self, name, calling_convention="cdecl"): - """Return the given name according to the selected calling convention""" - if calling_convention not in self.access: - raise LookupError( - "Unknown calling convention '{}' for function '{}'".format( - calling_convention, name - ) - ) - return getattr(self.access[calling_convention], name) - - def has(self, name, calling_convention="cdecl"): - """Return True if this given calling convention finds the given 'name'""" - if calling_convention not in self.access: - return False - return hasattr(self.access[calling_convention], name) - - def __getattr__(self, name): - return getattr(self.access["cdecl"], name) - - def __init__(self): - self.other_dirs = [] - - def __call__(self, libname): - """Given the name of a library, load it.""" - paths = self.getpaths(libname) - - for path in paths: - # noinspection PyBroadException - try: - return self.Lookup(path) - except Exception: # pylint: disable=broad-except - pass - - raise ImportError("Could not load %s." % libname) - - def getpaths(self, libname): - """Return a list of paths where the library might be found.""" - if os.path.isabs(libname): - yield libname - else: - # search through a prioritized series of locations for the library - - # we first search any specific directories identified by user - for dir_i in self.other_dirs: - for fmt in self.name_formats: - # dir_i should be absolute already - yield os.path.join(dir_i, fmt % libname) - - # check if this code is even stored in a physical file - try: - this_file = __file__ - except NameError: - this_file = None - - # then we search the directory where the generated python interface is stored - if this_file is not None: - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname)) - - # now, use the ctypes tools to try to find the library - for fmt in self.name_formats: - path = ctypes.util.find_library(fmt % libname) - if path: - yield path - - # then we search all paths identified as platform-specific lib paths - for path in self.getplatformpaths(libname): - yield path - - # Finally, we'll try the users current working directory - for fmt in self.name_formats: - yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname)) - - def getplatformpaths(self, _libname): # pylint: disable=no-self-use - """Return all the library paths available in this platform""" - return [] - - -# Darwin (Mac OS X) - - -class DarwinLibraryLoader(LibraryLoader): - """Library loader for MacOS""" - - name_formats = [ - "lib%s.dylib", - "lib%s.so", - "lib%s.bundle", - "%s.dylib", - "%s.so", - "%s.bundle", - "%s", - ] - - class Lookup(LibraryLoader.Lookup): - """ - Looking up library files for this platform (Darwin aka MacOS) - """ - - # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead - # of the default RTLD_LOCAL. Without this, you end up with - # libraries not being loadable, resulting in "Symbol not found" - # errors - mode = ctypes.RTLD_GLOBAL - - def getplatformpaths(self, libname): - if os.path.pathsep in libname: - names = [libname] - else: - names = [fmt % libname for fmt in self.name_formats] - - for directory in self.getdirs(libname): - for name in names: - yield os.path.join(directory, name) - - @staticmethod - def getdirs(libname): - """Implements the dylib search as specified in Apple documentation: - - http://developer.apple.com/documentation/DeveloperTools/Conceptual/ - DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html - - Before commencing the standard search, the method first checks - the bundle's ``Frameworks`` directory if the application is running - within a bundle (OS X .app). - """ - - dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH") - if not dyld_fallback_library_path: - dyld_fallback_library_path = [ - os.path.expanduser("~/lib"), - "/usr/local/lib", - "/usr/lib", - ] - - dirs = [] - - if "/" in libname: - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - else: - dirs.extend(_environ_path("LD_LIBRARY_PATH")) - dirs.extend(_environ_path("DYLD_LIBRARY_PATH")) - dirs.extend(_environ_path("LD_RUN_PATH")) - - if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app": - dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks")) - - dirs.extend(dyld_fallback_library_path) - - return dirs - - -# Posix - - -class PosixLibraryLoader(LibraryLoader): - """Library loader for POSIX-like systems (including Linux)""" - - _ld_so_cache = None - - _include = re.compile(r"^\s*include\s+(?P.*)") - - name_formats = ["lib%s.so", "%s.so", "%s"] - - class _Directories(dict): - """Deal with directories""" - - def __init__(self): - dict.__init__(self) - self.order = 0 - - def add(self, directory): - """Add a directory to our current set of directories""" - if len(directory) > 1: - directory = directory.rstrip(os.path.sep) - # only adds and updates order if exists and not already in set - if not os.path.exists(directory): - return - order = self.setdefault(directory, self.order) - if order == self.order: - self.order += 1 - - def extend(self, directories): - """Add a list of directories to our set""" - for a_dir in directories: - self.add(a_dir) - - def ordered(self): - """Sort the list of directories""" - return (i[0] for i in sorted(self.items(), key=lambda d: d[1])) - - def _get_ld_so_conf_dirs(self, conf, dirs): - """ - Recursive function to help parse all ld.so.conf files, including proper - handling of the `include` directive. - """ - - try: - with open(conf) as fileobj: - for dirname in fileobj: - dirname = dirname.strip() - if not dirname: - continue - - match = self._include.match(dirname) - if not match: - dirs.add(dirname) - else: - for dir2 in glob.glob(match.group("pattern")): - self._get_ld_so_conf_dirs(dir2, dirs) - except IOError: - pass - - def _create_ld_so_cache(self): - # Recreate search path followed by ld.so. This is going to be - # slow to build, and incorrect (ld.so uses ld.so.cache, which may - # not be up-to-date). Used only as fallback for distros without - # /sbin/ldconfig. - # - # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted. - - directories = self._Directories() - for name in ( - "LD_LIBRARY_PATH", - "SHLIB_PATH", # HP-UX - "LIBPATH", # OS/2, AIX - "LIBRARY_PATH", # BE/OS - ): - if name in os.environ: - directories.extend(os.environ[name].split(os.pathsep)) - - self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories) - - bitage = platform.architecture()[0] - - unix_lib_dirs_list = [] - if bitage.startswith("64"): - # prefer 64 bit if that is our arch - unix_lib_dirs_list += ["/lib64", "/usr/lib64"] - - # must include standard libs, since those paths are also used by 64 bit - # installs - unix_lib_dirs_list += ["/lib", "/usr/lib"] - if sys.platform.startswith("linux"): - # Try and support multiarch work in Ubuntu - # https://wiki.ubuntu.com/MultiarchSpec - if bitage.startswith("32"): - # Assume Intel/AMD x86 compat - unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"] - elif bitage.startswith("64"): - # Assume Intel/AMD x86 compatible - unix_lib_dirs_list += [ - "/lib/x86_64-linux-gnu", - "/usr/lib/x86_64-linux-gnu", - ] - else: - # guess... - unix_lib_dirs_list += glob.glob("/lib/*linux-gnu") - directories.extend(unix_lib_dirs_list) - - cache = {} - lib_re = re.compile(r"lib(.*)\.s[ol]") - # ext_re = re.compile(r"\.s[ol]$") - for our_dir in directories.ordered(): - try: - for path in glob.glob("%s/*.s[ol]*" % our_dir): - file = os.path.basename(path) - - # Index by filename - cache_i = cache.setdefault(file, set()) - cache_i.add(path) - - # Index by library name - match = lib_re.match(file) - if match: - library = match.group(1) - cache_i = cache.setdefault(library, set()) - cache_i.add(path) - except OSError: - pass - - self._ld_so_cache = cache - - def getplatformpaths(self, libname): - if self._ld_so_cache is None: - self._create_ld_so_cache() - - result = self._ld_so_cache.get(libname, set()) - for i in result: - # we iterate through all found paths for library, since we may have - # actually found multiple architectures or other library types that - # may not load - yield i - - -# Windows - - -class WindowsLibraryLoader(LibraryLoader): - """Library loader for Microsoft Windows""" - - name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"] - - class Lookup(LibraryLoader.Lookup): - """Lookup class for Windows libraries...""" - - def __init__(self, path): - super(WindowsLibraryLoader.Lookup, self).__init__(path) - self.access["stdcall"] = ctypes.windll.LoadLibrary(path) - - -# Platform switching - -# If your value of sys.platform does not appear in this dict, please contact -# the Ctypesgen maintainers. - -loaderclass = { - "darwin": DarwinLibraryLoader, - "cygwin": WindowsLibraryLoader, - "win32": WindowsLibraryLoader, - "msys": WindowsLibraryLoader, -} - -load_library = loaderclass.get(sys.platform, PosixLibraryLoader)() - - -def add_library_search_dirs(other_dirs): - """ - Add libraries to search paths. - If library paths are relative, convert them to absolute with respect to this - file's directory - """ - for path in other_dirs: - if not os.path.isabs(path): - path = os.path.abspath(path) - load_library.other_dirs.append(path) - - -del loaderclass - -# End loader - -add_library_search_dirs([]) - -# No libraries - -# No modules - -__uint8_t = c_ubyte# /usr/include/x86_64-linux-gnu/bits/types.h: 38 - -__uint16_t = c_ushort# /usr/include/x86_64-linux-gnu/bits/types.h: 40 - -__uint32_t = c_uint# /usr/include/x86_64-linux-gnu/bits/types.h: 42 - -__uint_least16_t = __uint16_t# /usr/include/x86_64-linux-gnu/bits/types.h: 55 - -uint8_t = __uint8_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 24 - -uint32_t = __uint32_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 26 - -uint_least16_t = __uint_least16_t# /usr/include/stdint.h: 50 - -pb_byte_t = uint8_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 241 - -pb_type_t = pb_byte_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 250 - -pb_size_t = uint_least16_t# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 326 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 -class struct_pb_istream_s(Structure): - pass - -pb_istream_t = struct_pb_istream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 332 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 -class struct_pb_ostream_s(Structure): - pass - -pb_ostream_t = struct_pb_ostream_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 333 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 353 -class struct_pb_field_iter_s(Structure): - pass - -pb_field_iter_t = struct_pb_field_iter_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 334 - -# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 340 -class struct_pb_msgdesc_s(Structure): - pass - -pb_msgdesc_t = struct_pb_msgdesc_s# /jrtc/jbpf-protobuf/3p/nanopb/pb.h: 339 - -struct_pb_msgdesc_s.__slots__ = [ - 'field_info', - 'submsg_info', - 'default_value', - 'field_callback', - 'field_count', - 'required_field_count', - 'largest_tag', -] -struct_pb_msgdesc_s._fields_ = [ - ('field_info', POINTER(uint32_t)), - ('submsg_info', POINTER(POINTER(pb_msgdesc_t))), - ('default_value', POINTER(pb_byte_t)), - ('field_callback', CFUNCTYPE(UNCHECKED(c_bool), POINTER(pb_istream_t), POINTER(pb_ostream_t), POINTER(pb_field_iter_t))), - ('field_count', pb_size_t), - ('required_field_count', pb_size_t), - ('largest_tag', pb_size_t), -] - -struct_pb_field_iter_s.__slots__ = [ - 'descriptor', - 'message', - 'index', - 'field_info_index', - 'required_field_index', - 'submessage_index', - 'tag', - 'data_size', - 'array_size', - 'type', - 'pField', - 'pData', - 'pSize', - 'submsg_desc', -] -struct_pb_field_iter_s._fields_ = [ - ('descriptor', POINTER(pb_msgdesc_t)), - ('message', POINTER(None)), - ('index', pb_size_t), - ('field_info_index', pb_size_t), - ('required_field_index', pb_size_t), - ('submessage_index', pb_size_t), - ('tag', pb_size_t), - ('data_size', pb_size_t), - ('array_size', pb_size_t), - ('type', pb_type_t), - ('pField', POINTER(None)), - ('pData', POINTER(None)), - ('pSize', POINTER(None)), - ('submsg_desc', POINTER(pb_msgdesc_t)), -] - -# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 15 -class struct__simple_input_pb(Structure): - pass - -struct__simple_input_pb.__slots__ = [ - 'aggregate_counter', -] -struct__simple_input_pb._fields_ = [ - ('aggregate_counter', c_int32), -] - -simple_input_pb = struct__simple_input_pb# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 15 - -# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 35 -for _lib in _libs.values(): - try: - simple_input_pb_msg = (pb_msgdesc_t).in_dll(_lib, "simple_input_pb_msg") - break - except: - pass - -# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 27 -try: - simple_input_pb_aggregate_counter_tag = 1 -except: - pass - -# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 38 -try: - simple_input_pb_fields = pointer(simple_input_pb_msg) -except: - pass - -# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 41 -try: - SIMPLE_INPUT_PB_H_MAX_SIZE = simple_input_pb_size -except: - pass - -# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 42 -try: - simple_input_pb_size = 11 -except: - pass - -_simple_input_pb = struct__simple_input_pb# /jrtc/sample_apps/jbpf_codelets/simple_input_protobuf/simple_input.pb.h: 15 - -# No inserted files - -# No prefix-stripping - diff --git a/setup_jrtc_env.sh b/setup_jrtc_env.sh index a635cd3c..dad2d40b 100755 --- a/setup_jrtc_env.sh +++ b/setup_jrtc_env.sh @@ -2,7 +2,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT license. -export PYTHONMALLOC=malloc export JRTC_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)" export JRTC_OUT_DIR=$JRTC_PATH/out export JRTC_APP_PATH=$JRTC_OUT_DIR/lib/ diff --git a/src/wrapper_apis/python/jrtc_router_stream_id.py b/src/wrapper_apis/python/jrtc_router_stream_id.py index 02cdb26a..d3066e5f 100644 --- a/src/wrapper_apis/python/jrtc_router_stream_id.py +++ b/src/wrapper_apis/python/jrtc_router_stream_id.py @@ -53,10 +53,8 @@ def generate_id(self, fwd_dst, device_id, stream_path, stream_name): b_stream_path = None b_stream_name = None if stream_path != None: - #stream_path = stream_path.encode("utf-8") b_stream_path = ctypes.create_string_buffer(stream_path) if stream_name != None: - #stream_name = stream_name.encode("utf-8") b_stream_name = ctypes.create_string_buffer(stream_name) res = stream_id_lib.jrtc_router_generate_stream_id( From a8a4e68ede1bb2a12a339d6affe49065e4190a28 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 12:41:19 +0100 Subject: [PATCH 08/20] Fix --- sample_apps/advanced_example_py/advanced_example1.py | 2 +- sample_apps/advanced_example_py/advanced_example2.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index ad729f37..f6e585de 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -22,7 +22,7 @@ # Define the state variables for the application class AppStateVars(ctypes.Structure): _fields_ = [ - ("app", ctypes.py_object), + ("app", ctypes.py_object), # add custom fields below ("agg_cnt", ctypes.c_int32) diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index 12f35dd7..b1f69486 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -22,7 +22,7 @@ # Define the state variables for the application class AppStateVars(ctypes.Structure): _fields_ = [ - ("app", ctypes.py_object), + ("app", ctypes.py_object), # add custom fields below ("agg_cnt", ctypes.c_int32), From 824b77d018864f58c17d2e0898d7709d4acf05e6 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 13:32:55 +0100 Subject: [PATCH 09/20] Fix --- src/wrapper_apis/python/jrtc_app.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/wrapper_apis/python/jrtc_app.py b/src/wrapper_apis/python/jrtc_app.py index ee852d3a..ae9056b1 100644 --- a/src/wrapper_apis/python/jrtc_app.py +++ b/src/wrapper_apis/python/jrtc_app.py @@ -121,15 +121,21 @@ def init(self) -> int: stream.sid.stream_source, stream.sid.io_map, ) - print(3) if res != 1: print(f"{self.c_struct.app_cfg.context}:: Failed to generate stream ID for stream {i}") return -1 + _sid = si.sid si.sid = si.sid.convert_to_struct_jrtc_router_stream_id() if stream.appChannel: si.chan_ctx = jrtc_router_channel_create( - self.c_struct.env_ctx.dapp_ctx, stream.appChannel, si.sid + self.c_struct.env_ctx.dapp_ctx, + stream.appChannel.contents.is_output, + stream.appChannel.contents.num_elems, + stream.appChannel.contents.elem_size, + _sid, + None, + 0, ) if not si.chan_ctx: print(f"{self.c_struct.app_cfg.context}:: Failed to create channel for stream {i}") @@ -209,24 +215,24 @@ def run(self): self.cleanup() def get_stream(self, stream_idx: int) -> Optional[JrtcRouterStreamId]: - if 0 <= stream_idx < len(self.stream_items): - return self.stream_items[stream_idx].sid + if stream_id < 0 or stream_idx >= len(self.stream_items): + return + return self.stream_items[stream_idx].sid def get_chan_ctx(self, stream_idx: int) -> Optional[ChannelCtx]: - if 0 <= stream_idx < len(self.stream_items): - return self.stream_items[stream_idx].chan_ctx + if stream_idx < 0 or stream_idx >= len(self.stream_items): + return + return self.stream_items[stream_idx].chan_ctx def jrtc_app_create(capsule, app_cfg: JrtcAppCfg_t, app_handler: JrtcAppHandler, app_state): env_ctx = get_ctx_from_capsule(capsule) app_handler_c = JrtcAppHandler(app_handler) - print(f"jrtc_app_create()") app_instance = JrtcApp( env_ctx=env_ctx, app_cfg=app_cfg, app_handler=app_handler_c, app_state=ctypes.cast(ctypes.pointer(app_state), ctypes.c_void_p) ) - #return ctypes.POINTER(JrtcApp)(app_instance) return app_instance def jrtc_app_run(app) -> None: From 0899e5f073eae242518ff03de20af136207450b7 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 14:00:48 +0100 Subject: [PATCH 10/20] Fix --- src/wrapper_apis/python/jrtc_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wrapper_apis/python/jrtc_app.py b/src/wrapper_apis/python/jrtc_app.py index ae9056b1..a4d56907 100644 --- a/src/wrapper_apis/python/jrtc_app.py +++ b/src/wrapper_apis/python/jrtc_app.py @@ -215,7 +215,7 @@ def run(self): self.cleanup() def get_stream(self, stream_idx: int) -> Optional[JrtcRouterStreamId]: - if stream_id < 0 or stream_idx >= len(self.stream_items): + if stream_idx < 0 or stream_idx >= len(self.stream_items): return return self.stream_items[stream_idx].sid From 944e3dc6cca86939881e9d46bf6f9f60bc6e88d2 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 20:46:45 +0100 Subject: [PATCH 11/20] Fix pipeline --- azure-pipeline.yaml | 4 +--- src/rest_api_lib/src/lib.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/azure-pipeline.yaml b/azure-pipeline.yaml index 50a7a61c..f8732dde 100644 --- a/azure-pipeline.yaml +++ b/azure-pipeline.yaml @@ -5,14 +5,12 @@ trigger: branches: include: - main - - stable - gh-readonly-queue/main/* pr: branches: include: - main - - stable - gh-readonly-queue/main/* pool: @@ -30,7 +28,7 @@ schedules: displayName: Daily scheduled build branches: include: - - stable + - main always: true variables: diff --git a/src/rest_api_lib/src/lib.rs b/src/rest_api_lib/src/lib.rs index e134ca3b..72063951 100644 --- a/src/rest_api_lib/src/lib.rs +++ b/src/rest_api_lib/src/lib.rs @@ -22,7 +22,6 @@ use tokio::runtime::Runtime; use tokio::sync::Mutex; use utoipa::{OpenApi, ToSchema}; use utoipa_swagger_ui::SwaggerUi; -use std::env; use std::collections::HashMap; #[repr(C)] @@ -285,12 +284,9 @@ async fn load_app( }; // Free app_name memory after callback - unsafe { - // Free app_name memory after callback - let _ = CString::from_raw(app_name_ptr); - let _ = CString::from_raw(app_path_ptr); - let _ = CString::from_raw(app_type_ptr); - } + let _ = CString::from_raw(app_name_ptr); + let _ = CString::from_raw(app_path_ptr); + let _ = CString::from_raw(app_type_ptr); } match response { @@ -428,6 +424,6 @@ pub extern "C" fn jrtc_start_rest_server(ptr: *mut c_void, port: u16, cbs: *mut spawn_server((*handle).clone(), port, callbacks); // Convert back into raw pointer to avoid premature drop - Arc::into_raw(handle); + let _ = Arc::into_raw(handle); } } From 5b2f1c558305b6a665acf680a59955e4dc6ee117 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 21:00:30 +0100 Subject: [PATCH 12/20] Add debug --- helper_build_files/build_jrtc.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/helper_build_files/build_jrtc.sh b/helper_build_files/build_jrtc.sh index 0c383e81..6e300cc5 100755 --- a/helper_build_files/build_jrtc.sh +++ b/helper_build_files/build_jrtc.sh @@ -49,6 +49,7 @@ fi if ! make $MAKE_FLAGS; then echo "Error building!" + cat /jrtc/build/src/rest_api_lib/rest_api_lib-prefix/src/rest_api_lib-stamp/rest_api_lib-build-*.log || true exit 1 fi From ab3bb08337e9a480ca60c93a7b744a528a3fe467 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Sat, 10 May 2025 21:12:09 +0100 Subject: [PATCH 13/20] Pin yoke version --- src/rest_api_lib/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rest_api_lib/Cargo.toml b/src/rest_api_lib/Cargo.toml index e2633d32..9480c808 100644 --- a/src/rest_api_lib/Cargo.toml +++ b/src/rest_api_lib/Cargo.toml @@ -20,8 +20,8 @@ utoipa = { version = "4.2.3", features = ["axum_extras"] } utoipa-swagger-ui = { version = "7.1.0", features = ["axum"] } zerofrom = "=0.1.5" litemap = "=0.7.4" +yoke = "=0.7.3" [lib] name = "jrtc_rest_api_lib" crate-type = ["staticlib"] - From ba451b5647ba7c0db339183b532ad0cb541602b0 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 09:24:18 +0100 Subject: [PATCH 14/20] Install rust 1.82 --- deploy/ubuntu22_04.Dockerfile | 5 ++++- deploy/ubuntu24_04.Dockerfile | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/deploy/ubuntu22_04.Dockerfile b/deploy/ubuntu22_04.Dockerfile index c784c177..b051ba37 100644 --- a/deploy/ubuntu22_04.Dockerfile +++ b/deploy/ubuntu22_04.Dockerfile @@ -48,7 +48,10 @@ RUN pip3 install ctypesgen RUN apt install -y python3-dev zip # install rust -RUN apt install -y cargo +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.82 \ + && . "$HOME/.cargo/env" \ + && rustc --version + ENV PATH="/root/.cargo/bin:${PATH}" ## build the jrtc and doxygen diff --git a/deploy/ubuntu24_04.Dockerfile b/deploy/ubuntu24_04.Dockerfile index ccc24b38..68d2848a 100644 --- a/deploy/ubuntu24_04.Dockerfile +++ b/deploy/ubuntu24_04.Dockerfile @@ -49,7 +49,10 @@ RUN pip3 install -r /jrtc/jbpf-protobuf/3p/nanopb/requirements.txt --break-syste ## RUN apt install -y python3-protobuf python3-grpcio # install rust -RUN apt install -y cargo +RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.82 \ + && . "$HOME/.cargo/env" \ + && rustc --version + ENV PATH="/root/.cargo/bin:${PATH}" ## build the jrtc and doxygen From b2d2b1beb7501eaf74ac08baac96e487016d1d58 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 10:09:47 +0100 Subject: [PATCH 15/20] Revert to rust 1.75 --- deploy/ubuntu22_04.Dockerfile | 5 +---- deploy/ubuntu24_04.Dockerfile | 5 +---- src/rest_api_lib/Cargo.toml | 1 + 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/deploy/ubuntu22_04.Dockerfile b/deploy/ubuntu22_04.Dockerfile index b051ba37..c784c177 100644 --- a/deploy/ubuntu22_04.Dockerfile +++ b/deploy/ubuntu22_04.Dockerfile @@ -48,10 +48,7 @@ RUN pip3 install ctypesgen RUN apt install -y python3-dev zip # install rust -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.82 \ - && . "$HOME/.cargo/env" \ - && rustc --version - +RUN apt install -y cargo ENV PATH="/root/.cargo/bin:${PATH}" ## build the jrtc and doxygen diff --git a/deploy/ubuntu24_04.Dockerfile b/deploy/ubuntu24_04.Dockerfile index 68d2848a..ccc24b38 100644 --- a/deploy/ubuntu24_04.Dockerfile +++ b/deploy/ubuntu24_04.Dockerfile @@ -49,10 +49,7 @@ RUN pip3 install -r /jrtc/jbpf-protobuf/3p/nanopb/requirements.txt --break-syste ## RUN apt install -y python3-protobuf python3-grpcio # install rust -RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain 1.82 \ - && . "$HOME/.cargo/env" \ - && rustc --version - +RUN apt install -y cargo ENV PATH="/root/.cargo/bin:${PATH}" ## build the jrtc and doxygen diff --git a/src/rest_api_lib/Cargo.toml b/src/rest_api_lib/Cargo.toml index 9480c808..510a637b 100644 --- a/src/rest_api_lib/Cargo.toml +++ b/src/rest_api_lib/Cargo.toml @@ -21,6 +21,7 @@ utoipa-swagger-ui = { version = "7.1.0", features = ["axum"] } zerofrom = "=0.1.5" litemap = "=0.7.4" yoke = "=0.7.3" +zerovec = "=0.11.0" [lib] name = "jrtc_rest_api_lib" From 6f8c12a57c0a9a5cfb1806bc346d915373334ed7 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 10:46:17 +0100 Subject: [PATCH 16/20] Use Cargo.lock to pin the versions --- src/rest_api_lib/Cargo.lock | 2254 +++++++++++++++++++++++++++++++++++ src/rest_api_lib/Cargo.toml | 2 - 2 files changed, 2254 insertions(+), 2 deletions(-) create mode 100644 src/rest_api_lib/Cargo.lock diff --git a/src/rest_api_lib/Cargo.lock b/src/rest_api_lib/Cargo.lock new file mode 100644 index 00000000..736217d8 --- /dev/null +++ b/src/rest_api_lib/Cargo.lock @@ -0,0 +1,2254 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower 0.5.2", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-server" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad46c3ec4e12f4a4b6835e173ba21c25e484c9d02b49770bf006ce5367c036" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower 0.4.13", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64-bytes" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce54e4e485fa0eed9c3aa5348162be09168f75bb5be7bc6587bcf2a65ee1386" +dependencies = [ + "base64", + "serde", +] + +[[package]] +name = "bitflags" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "flate2" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-io", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84b26c544d002229e640969970a2e74021aadf6e2f96372b9c58eff97de08eb3" + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" +dependencies = [ + "futures-util", + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 0.26.11", +] + +[[package]] +name = "hyper-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "libc", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "137d96353afc8544d437e8a99eceb10ab291352699573b0de5b08bda38c78c60" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c0aa2536adc14c07e2a521e95512b75ed8ef832f0fdf9299d4a0a45d2be2a9d" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c17d8f6524fdca4471101dd71f0a132eb6382b5d6d7f2970441cb25f6f435a" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545c6c3e8bf9580e2dafee8de6f9ec14826aaf359787789c7724f1f85f47d3dc" + +[[package]] +name = "icu_normalizer" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accb85c5b2e76f8dade22978b3795ae1e550198c6cfc7e915144e17cd6e2ab56" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3744fecc0df9ce19999cdaf1f9f3a48c253431ce1d67ef499128fe9d0b607ab" + +[[package]] +name = "icu_properties" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db9e559598096627aeca8cdfb98138a70eb4078025f8d1d5f2416a361241f756" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70a8b51ee5dd4ff8f20ee9b1dd1bc07afc110886a3747b1fec04cc6e5a15815" + +[[package]] +name = "icu_provider" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba58e782287eb6950247abbf11719f83f5d4e4a5c1f2cd490d30a334bc47c2f4" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "json" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078e285eafdfb6c4b434e0d31e8cfcb5115b651496faca5749b88fafd4f23bfd" + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quinn" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.12", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.12", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower 0.5.2", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.26.11", + "windows-registry", +] + +[[package]] +name = "rest_api_lib" +version = "0.1.0" +dependencies = [ + "axum", + "axum-server", + "base64", + "base64-bytes", + "chrono", + "json", + "litemap", + "serde", + "serde_derive", + "serde_json", + "tokio", + "utoipa", + "utoipa-swagger-ui", + "zerofrom", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rust-embed" +version = "8.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60e425e204264b144d4c929d126d0de524b40a961686414bab5040f7465c71be" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.101", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustls" +version = "0.23.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" + +[[package]] +name = "socket2" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.101" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3da5db5a963e24bc68be8b17b6fa82814bb22ee8660f192bb182771d498f09a3" + +[[package]] +name = "toml_edit" +version = "0.22.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "310068873db2c5b3e7659d2cc35d21855dbafa50d1ce336397c666e3cb08137e" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utoipa" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen", +] + +[[package]] +name = "utoipa-gen" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c24e8ab68ff9ee746aad22d39b5535601e6416d1b0feeabf78be986a5c4392" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 2.0.101", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943e0ff606c6d57d410fd5663a4d7c074ab2c5f14ab903b9514565e59fa1189e" +dependencies = [ + "axum", + "mime_guess", + "regex", + "reqwest", + "rust-embed", + "serde", + "serde_json", + "url", + "utoipa", + "zip", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.101", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings 0.4.0", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "windows-link" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" + +[[package]] +name = "windows-registry" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" +dependencies = [ + "windows-result", + "windows-strings 0.3.1", + "windows-targets 0.53.0", +] + +[[package]] +name = "windows-result" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06928c8748d81b05c9be96aad92e1b6ff01833332f281e8cfca3be4b35fc9ec" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "yoke" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.101", +] + +[[package]] +name = "zip" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "num_enum", + "thiserror 1.0.69", +] diff --git a/src/rest_api_lib/Cargo.toml b/src/rest_api_lib/Cargo.toml index 510a637b..6516e085 100644 --- a/src/rest_api_lib/Cargo.toml +++ b/src/rest_api_lib/Cargo.toml @@ -20,8 +20,6 @@ utoipa = { version = "4.2.3", features = ["axum_extras"] } utoipa-swagger-ui = { version = "7.1.0", features = ["axum"] } zerofrom = "=0.1.5" litemap = "=0.7.4" -yoke = "=0.7.3" -zerovec = "=0.11.0" [lib] name = "jrtc_rest_api_lib" From d046529543355cf51f9cbb1b8cd2205a57248492 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 11:17:31 +0100 Subject: [PATCH 17/20] Minor --- src/rest_api_lib/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rest_api_lib/Cargo.toml b/src/rest_api_lib/Cargo.toml index 6516e085..b518dc23 100644 --- a/src/rest_api_lib/Cargo.toml +++ b/src/rest_api_lib/Cargo.toml @@ -23,4 +23,4 @@ litemap = "=0.7.4" [lib] name = "jrtc_rest_api_lib" -crate-type = ["staticlib"] +crate-type = ["staticlib"] \ No newline at end of file From 40f471dd80d1a08494937fb35ff6bc2753d4af15 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 11:18:21 +0100 Subject: [PATCH 18/20] Minor --- src/rest_api_lib/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rest_api_lib/Cargo.toml b/src/rest_api_lib/Cargo.toml index b518dc23..6516e085 100644 --- a/src/rest_api_lib/Cargo.toml +++ b/src/rest_api_lib/Cargo.toml @@ -23,4 +23,4 @@ litemap = "=0.7.4" [lib] name = "jrtc_rest_api_lib" -crate-type = ["staticlib"] \ No newline at end of file +crate-type = ["staticlib"] From 10e231b8503181da7aef1747afc0872a64df94a8 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 14:03:44 +0100 Subject: [PATCH 19/20] Remove testing code --- sample_apps/advanced_example_py/advanced_example1.py | 6 ------ sample_apps/advanced_example_py/advanced_example2.py | 6 ------ sample_apps/first_example_py/first_example.py | 6 ------ 3 files changed, 18 deletions(-) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index f6e585de..25dcd581 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -48,12 +48,6 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents - print("BEFORE") - a = 10000 * [0] - for i in range(10000): - a[i] = 100 * [1] - print("AFTER") - if stream_idx == GENERATOR_OUT_STREAM_IDX: # Extract data from the received entry data = ctypes.cast(data_entry.data, ctypes.POINTER(example_msg)).contents diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index b1f69486..a992c8ac 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -46,12 +46,6 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents - print("BEFORE") - a = 10000 * [0] - for i in range(10000): - a[i] = 100 * [1] - print("AFTER") - if stream_idx == GENERATOR_PB_OUT_STREAM_IDX: state.received_counter += 1 diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index a4bcb2ae..d48672b5 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -46,12 +46,6 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents data_entry = data_entry_ptr.contents - print("BEFORE") - a = 10000 * [0] - for i in range(10000): - a[i] = 100 * [1] - print("AFTER") - if stream_idx == GENERATOR_OUT_STREAM_IDX: state.received_counter += 1 From aabf7f4959ddc8d188056d03a78f2f6ce66fd8d9 Mon Sep 17 00:00:00 2001 From: Zhihua Lai Date: Mon, 12 May 2025 20:29:38 +0100 Subject: [PATCH 20/20] Final fix? --- .../advanced_example_py/advanced_example1.py | 22 ++-- .../advanced_example_py/advanced_example2.py | 22 ++-- sample_apps/first_example_py/first_example.py | 27 ++--- src/pythonapp_loader/jrtc_pythonapp_loader.c | 2 +- src/wrapper_apis/python/jrtc_app.py | 103 +++++++++--------- 5 files changed, 76 insertions(+), 100 deletions(-) diff --git a/sample_apps/advanced_example_py/advanced_example1.py b/sample_apps/advanced_example_py/advanced_example1.py index 25dcd581..8c0765e1 100644 --- a/sample_apps/advanced_example_py/advanced_example1.py +++ b/sample_apps/advanced_example_py/advanced_example1.py @@ -3,6 +3,7 @@ import os import sys import ctypes +from dataclasses import dataclass JRTC_APP_PATH = os.environ.get("JRTC_APP_PATH") if JRTC_APP_PATH is None: @@ -20,18 +21,13 @@ ########################################################################## # Define the state variables for the application -class AppStateVars(ctypes.Structure): - _fields_ = [ - ("app", ctypes.py_object), - - # add custom fields below - ("agg_cnt", ctypes.c_int32) - ] - +@dataclass +class AppStateVars: + app: JrtcApp + agg_cnt: int ########################################################################## -# Handler callback function (this function gets called by the C library) -def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(struct_jrtc_router_data_entry), state_ptr: int): +def app_handler(timeout: bool, stream_idx: int, data_entry: struct_jrtc_router_data_entry, state: AppStateVars): GENERATOR_OUT_STREAM_IDX = 0 APP2_OUT_STREAM_IDX = 1 @@ -44,10 +40,6 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s else: - # Dereference the pointer arguments - state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents - data_entry = data_entry_ptr.contents - if stream_idx == GENERATOR_OUT_STREAM_IDX: # Extract data from the received entry data = ctypes.cast(data_entry.data, ctypes.POINTER(example_msg)).contents @@ -129,7 +121,7 @@ def jrtc_start_app(capsule): ) # Initialize the app - state = AppStateVars(agg_cnt=0) + state = AppStateVars(agg_cnt=0, app=None) state.app = jrtc_app_create(capsule, app_cfg, app_handler, state) # run the app - This is blocking until the app exits diff --git a/sample_apps/advanced_example_py/advanced_example2.py b/sample_apps/advanced_example_py/advanced_example2.py index a992c8ac..ae957043 100644 --- a/sample_apps/advanced_example_py/advanced_example2.py +++ b/sample_apps/advanced_example_py/advanced_example2.py @@ -3,6 +3,7 @@ import os import sys import ctypes +from dataclasses import dataclass JRTC_APP_PATH = os.environ.get("JRTC_APP_PATH") if JRTC_APP_PATH is None: @@ -20,18 +21,14 @@ ########################################################################## # Define the state variables for the application -class AppStateVars(ctypes.Structure): - _fields_ = [ - ("app", ctypes.py_object), - - # add custom fields below - ("agg_cnt", ctypes.c_int32), - ("received_counter", ctypes.c_int) - ] +@dataclass +class AppStateVars: + app: JrtcApp + agg_cnt: int + received_counter: int ########################################################################## -# Handler callback function (this function gets called by the C library) -def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(struct_jrtc_router_data_entry), state_ptr: int): +def app_handler(timeout: bool, stream_idx: int, data_entry: struct_jrtc_router_data_entry, state: AppStateVars): GENERATOR_PB_OUT_STREAM_IDX = 0 APP2_OUT_STREAM_IDX = 1 @@ -42,9 +39,6 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s pass else: - # Dereference the pointer arguments - state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents - data_entry = data_entry_ptr.contents if stream_idx == GENERATOR_PB_OUT_STREAM_IDX: @@ -134,7 +128,7 @@ def jrtc_start_app(capsule): ) # Initialize the app - state = AppStateVars(agg_cnt=0, received_counter=0) + state = AppStateVars(agg_cnt=0, received_counter=0, app=None) state.app = jrtc_app_create(capsule, app_cfg, app_handler, state) # run the app - This is blocking until the app exists diff --git a/sample_apps/first_example_py/first_example.py b/sample_apps/first_example_py/first_example.py index d48672b5..646a63a9 100644 --- a/sample_apps/first_example_py/first_example.py +++ b/sample_apps/first_example_py/first_example.py @@ -3,6 +3,7 @@ import os import sys import ctypes +from dataclasses import dataclass JRTC_APP_PATH = os.environ.get("JRTC_APP_PATH") if JRTC_APP_PATH is None: @@ -16,22 +17,20 @@ simple_input = sys.modules.get('simple_input') from generated_data import example_msg from simple_input import simple_input +from jrtc_bindings import ( + struct_jrtc_router_data_entry, +) ########################################################################## # Define the state variables for the application -class AppStateVars(ctypes.Structure): - _fields_ = [ - ("app", ctypes.py_object), - - # add custom fields below - ("agg_cnt", ctypes.c_int), - ("received_counter", ctypes.c_int) - ] - +@dataclass +class AppStateVars: + app: JrtcApp + agg_cnt: int + received_counter: int ########################################################################## -# Handler callback function (this function gets called by the C library) -def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(struct_jrtc_router_data_entry), state_ptr: int): +def app_handler(timeout: bool, stream_idx: int, data_entry: struct_jrtc_router_data_entry, state: AppStateVars): GENERATOR_OUT_STREAM_IDX = 0 SIMPLE_INPUT_IN_STREAM_IDX = 1 @@ -42,10 +41,6 @@ def app_handler(timeout: bool, stream_idx: int, data_entry_ptr: ctypes.POINTER(s else: - # Dereference the pointer arguments - state = ctypes.cast(state_ptr, ctypes.POINTER(AppStateVars)).contents - data_entry = data_entry_ptr.contents - if stream_idx == GENERATOR_OUT_STREAM_IDX: state.received_counter += 1 @@ -111,7 +106,7 @@ def jrtc_start_app(capsule): ) # Initialize the app - state = AppStateVars(agg_cnt=0, received_counter=0) + state = AppStateVars(agg_cnt=0, received_counter=0, app=None) state.app = jrtc_app_create(capsule, app_cfg, app_handler, state) # run the app - This is blocking until the app exists diff --git a/src/pythonapp_loader/jrtc_pythonapp_loader.c b/src/pythonapp_loader/jrtc_pythonapp_loader.c index 8c5d5cf1..8883d0a7 100644 --- a/src/pythonapp_loader/jrtc_pythonapp_loader.c +++ b/src/pythonapp_loader/jrtc_pythonapp_loader.c @@ -360,7 +360,6 @@ jrtc_start_app(void* args) Py_XDECREF(pCapsule); cleanup_gil: - PyGILState_Release(gstate); if (ts1) { if (main_ts != ts1) { @@ -371,6 +370,7 @@ jrtc_start_app(void* args) PyThreadState_Swap(main_ts); Py_EndInterpreter(ts1); } + PyGILState_Release(gstate); if (Py_IsInitialized()) { Py_Finalize(); diff --git a/src/wrapper_apis/python/jrtc_app.py b/src/wrapper_apis/python/jrtc_app.py index a4d56907..843e0158 100644 --- a/src/wrapper_apis/python/jrtc_app.py +++ b/src/wrapper_apis/python/jrtc_app.py @@ -5,6 +5,7 @@ import os import sys import ctypes +from dataclasses import dataclass from ctypes import ( c_int, c_float, c_char_p, c_void_p, c_bool, POINTER, Structure, c_uint16, c_uint64 @@ -73,48 +74,43 @@ class JrtcAppCfg_t(Structure): ("inactivity_timeout_secs", c_float), ] -# Opaque types class ChannelCtx(ctypes.Structure): pass -class RouterDataEntry(ctypes.Structure): pass - -# Callback type definition -JrtcAppHandler = ctypes.CFUNCTYPE( - None, c_bool, c_int, POINTER(struct_jrtc_router_data_entry), c_void_p -) +class AppStateVars: pass class StreamItem(ctypes.Structure): sid: Optional[JrtcRouterStreamId] = None registered: bool = False chan_ctx: Optional[ChannelCtx] = None -class AppStateVars(ctypes.Structure): - pass - -class JrtcAppCStruct(Structure): - _fields_ = [ - ("env_ctx", JrtcAppEnv), - ("app_cfg", JrtcAppCfg_t), - ("app_handler", JrtcAppHandler), - ("app_state", ctypes.c_void_p), - ("last_received_time", ctypes.c_float), - ] +@dataclass +class JrtcAppData: + env_ctx: JrtcAppEnv + app_cfg: JrtcAppCfg_t + app_handler: Any + app_state: AppStateVars + last_received_time: float + def __init__(self, env_ctx, app_cfg, app_handler, app_state, last_received_time): + self.env_ctx = env_ctx + self.app_cfg = app_cfg + self.app_handler = app_handler + self.app_state = app_state + self.last_received_time = last_received_time class JrtcApp: def __init__(self, env_ctx, app_cfg, app_handler, app_state): super().__init__() - self.c_struct = JrtcAppCStruct(env_ctx, app_cfg, app_handler, app_state, time.monotonic()) + self.data = JrtcAppData(env_ctx, app_cfg, app_handler, app_state, time.monotonic()) self.stream_items: list[StreamItem] = [] def init(self) -> int: start_time = time.monotonic() self.last_received_time = start_time - for i in range(self.c_struct.app_cfg.num_streams): - stream = self.c_struct.app_cfg.streams[i] + for i in range(self.data.app_cfg.num_streams): + stream = self.data.app_cfg.streams[i] si = StreamItem() si.sid = JrtcRouterStreamId() - ## res = jrtc_router_generate_stream_id(&sid, s.sid.destination, s.sid.device_id, s.sid.stream_source, s.sid.io_map); res = si.sid.generate_id( stream.sid.destination, stream.sid.device_id, @@ -122,14 +118,14 @@ def init(self) -> int: stream.sid.io_map, ) if res != 1: - print(f"{self.c_struct.app_cfg.context}:: Failed to generate stream ID for stream {i}") + print(f"{self.data.app_cfg.context}:: Failed to generate stream ID for stream {i}") return -1 _sid = si.sid si.sid = si.sid.convert_to_struct_jrtc_router_stream_id() if stream.appChannel: si.chan_ctx = jrtc_router_channel_create( - self.c_struct.env_ctx.dapp_ctx, + self.data.env_ctx.dapp_ctx, stream.appChannel.contents.is_output, stream.appChannel.contents.num_elems, stream.appChannel.contents.elem_size, @@ -138,46 +134,46 @@ def init(self) -> int: 0, ) if not si.chan_ctx: - print(f"{self.c_struct.app_cfg.context}:: Failed to create channel for stream {i}") + print(f"{self.data.app_cfg.context}:: Failed to create channel for stream {i}") return -1 if stream.is_rx: - if not jrtc_router_channel_register_stream_id_req(self.c_struct.env_ctx.dapp_ctx, si.sid): - print(f"{self.c_struct.app_cfg.context}:: Failed to register stream {i}") + if not jrtc_router_channel_register_stream_id_req(self.data.env_ctx.dapp_ctx, si.sid): + print(f"{self.data.app_cfg.context}:: Failed to register stream {i}") return -1 si.registered = True self.stream_items.append(si) - if self.c_struct.app_cfg.initialization_timeout_secs > 0: - if time.monotonic() - start_time > self.c_struct.app_cfg.initialization_timeout_secs: - print(f"{self.c_struct.app_cfg.context}:: Initialization timeout") + if self.data.app_cfg.initialization_timeout_secs > 0: + if time.monotonic() - start_time > self.data.app_cfg.initialization_timeout_secs: + print(f"{self.data.app_cfg.context}:: Initialization timeout") return -1 - for i in range(self.c_struct.app_cfg.num_streams): - stream = self.c_struct.app_cfg.streams[i] + for i in range(self.data.app_cfg.num_streams): + stream = self.data.app_cfg.streams[i] si = self.stream_items[i] if not stream.is_rx and not si.chan_ctx: k = 0 while not jrtc_router_input_channel_exists(si.sid): time.sleep(0.1) if k == 10: - print(f"{self.c_struct.app_cfg.context}:: Waiting for creation of stream {i}") + print(f"{self.data.app_cfg.context}:: Waiting for creation of stream {i}") k = 0 else: k += 1 - if self.c_struct.app_cfg.initialization_timeout_secs > 0: - if time.monotonic() - start_time > self.c_struct.app_cfg.initialization_timeout_secs: - print(f"{self.c_struct.app_cfg.context}:: Timeout waiting for stream {i}") + if self.data.app_cfg.initialization_timeout_secs > 0: + if time.monotonic() - start_time > self.data.app_cfg.initialization_timeout_secs: + print(f"{self.data.app_cfg.context}:: Timeout waiting for stream {i}") return -1 return 0 def cleanup(self): - print(f"{self.c_struct.app_cfg.context}:: Cleaning up app") + print(f"{self.data.app_cfg.context}:: Cleaning up app") for si in self.stream_items: if si.registered: - jrtc_router_channel_deregister_stream_id_req(self.c_struct.env_ctx.dapp_ctx, si.sid) + jrtc_router_channel_deregister_stream_id_req(self.data.env_ctx.dapp_ctx, si.sid) if si.chan_ctx: jrtc_router_channel_destroy(si.chan_ctx) @@ -185,32 +181,32 @@ def run(self): if self.init() != 0: return - data_entries = get_data_entry_array_ptr(self.c_struct.app_cfg.q_size) - while not self.c_struct.env_ctx.app_exit: + data_entries = get_data_entry_array_ptr(self.data.app_cfg.q_size) + while not self.data.env_ctx.app_exit: now = time.monotonic() if ( - self.c_struct.app_cfg.inactivity_timeout_secs > 0 - and now - self.c_struct.last_received_time > self.c_struct.app_cfg.inactivity_timeout_secs + self.data.app_cfg.inactivity_timeout_secs > 0 + and now - self.data.last_received_time > self.data.app_cfg.inactivity_timeout_secs ): - self.c_struct.app_handler(True, -1, None, self.c_struct.app_state) + self.data.app_handler(True, -1, None, self.data.app_state) self.last_received_time = now - num_rcv = jrtc_router_receive(self.c_struct.env_ctx.dapp_ctx, data_entries, self.c_struct.app_cfg.q_size) + num_rcv = jrtc_router_receive(self.data.env_ctx.dapp_ctx, data_entries, self.data.app_cfg.q_size) for i in range(num_rcv): data_entry = data_entries[i] if not data_entry: continue - for sidx in range(self.c_struct.app_cfg.num_streams): - stream = self.c_struct.app_cfg.streams[sidx] + for sidx in range(self.data.app_cfg.num_streams): + stream = self.data.app_cfg.streams[sidx] si = self.stream_items[sidx] if stream.is_rx and jrtc_router_stream_id_matches_req(data_entry.stream_id, si.sid): - self.c_struct.app_handler(False, sidx, data_entry, self.c_struct.app_state) + self.data.app_handler(False, sidx, data_entry, self.data.app_state) break jrtc_router_channel_release_buf(data_entry.data) - self.c_struct.last_received_time = time.monotonic() + self.data.last_received_time = time.monotonic() - if self.c_struct.app_cfg.sleep_timeout_secs > 0: - time.sleep(max(self.c_struct.app_cfg.sleep_timeout_secs, 1e-9)) + if self.data.app_cfg.sleep_timeout_secs > 0: + time.sleep(max(self.data.app_cfg.sleep_timeout_secs, 1e-9)) self.cleanup() @@ -224,14 +220,13 @@ def get_chan_ctx(self, stream_idx: int) -> Optional[ChannelCtx]: return return self.stream_items[stream_idx].chan_ctx -def jrtc_app_create(capsule, app_cfg: JrtcAppCfg_t, app_handler: JrtcAppHandler, app_state): +def jrtc_app_create(capsule, app_cfg: JrtcAppCfg_t, app_handler, app_state): env_ctx = get_ctx_from_capsule(capsule) - app_handler_c = JrtcAppHandler(app_handler) app_instance = JrtcApp( env_ctx=env_ctx, app_cfg=app_cfg, - app_handler=app_handler_c, - app_state=ctypes.cast(ctypes.pointer(app_state), ctypes.c_void_p) + app_handler=app_handler, + app_state=app_state, ) return app_instance