1313// limitations under the License.
1414
1515%{
16+ #include < stdexcept>
17+ #include < vector>
18+
1619#include " fastdds/rtps/common/InstanceHandle.hpp"
1720
1821// Define a hash method in global scope for InstanceHandle_t types
@@ -26,60 +29,119 @@ long hash(const eprosima::fastdds::rtps::InstanceHandle_t& handle)
2629 }
2730 return ret;
2831}
29-
3032%}
3133
3234// SWIG does not support type conversion operators correctly unless converted to a normal method
3335%rename(get_guid) eprosima::fastdds::rtps::InstanceHandle_t::operator const GUID_t&;
3436
3537%ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator [] const ;
38+ %ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator [];
3639%ignore eprosima::fastdds::rtps::operator <<(std::ostream&, const InstanceHandle_t&);
3740%ignore eprosima::fastdds::rtps::operator >>(std::istream&, InstanceHandle_t&);
38- %rename(read_pointer_cast) eprosima::fastdds::rtps::InstanceHandleValue_t::operator const octet* () const ;
39- %rename(write_pointer_cast) eprosima::fastdds::rtps::InstanceHandleValue_t::operator octet* ();
40-
41- %typemap(in) eprosima::fastdds::rtps::InstanceHandleValue_t*(eprosima::fastdds::rtps::InstanceHandleValue_t temp)
42- {
43- if (PyTuple_Check ($input))
44- {
45- eprosima::fastdds::rtps::octet* buf = temp;
46- if (!PyArg_ParseTuple ($input, " BBBBBBBBBBBBBBBB" ,
47- buf, buf+1 , buf+2 , buf+3 , buf+4 , buf+5 , buf+6 , buf+7 , buf+8 ,
48- buf+9 , buf+10 , buf+11 , buf+12 , buf+13 , buf+14 , buf+15 ))
41+ %ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator const octet* () const ;
42+ %ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator octet* ();
43+
44+ %extend eprosima::fastdds::rtps::InstanceHandleValue_t {
45+
46+ // Constructor from a sequence of 16 bytes (tuple/list/bytes/bytearray)
47+ InstanceHandleValue_t (PyObject* seq) {
48+ eprosima::fastdds::rtps::InstanceHandleValue_t* self = new eprosima::fastdds::rtps::InstanceHandleValue_t ();
49+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
50+
51+ // Fast-path: bytes
52+ if (PyBytes_Check (seq)) {
53+ if (PyBytes_GET_SIZE (seq) == 16 )
54+ {
55+ const char * b = PyBytes_AS_STRING (seq);
56+ for (int i = 0 ; i < 16 ; ++i) (*self)[i] = (uint8_t )(unsigned char )b[i];
57+ }
58+ else
59+ {
60+ delete self;
61+ self = nullptr ;
62+ PyErr_SetString (PyExc_ValueError, " Expected 16 bytes" );
63+ }
64+ }
65+ // Fast-path: bytearray
66+ else if (PyByteArray_Check (seq))
4967 {
50- PyErr_SetString (PyExc_TypeError, " tuple must have 16 elements" );
51- SWIG_fail;
68+ if (PyByteArray_GET_SIZE (seq) == 16 )
69+ {
70+ const char * b = PyByteArray_AS_STRING (seq);
71+ for (int i = 0 ; i < 16 ; ++i) (*self)[i] = (uint8_t )(unsigned char )b[i];
72+ }
73+ else
74+ {
75+ delete self;
76+ self = nullptr ;
77+ PyErr_SetString (PyExc_ValueError, " Expected 16 bytes" );
78+ }
5279 }
53- $1 = &temp;
54- }
55- else
56- {
57- PyErr_SetString (PyExc_TypeError, " expected a tuple." );
58- SWIG_fail;
80+ else
81+ {
82+ // Generic fallback: iterable from 16 ints 0..255
83+ PyObject* it = PyObject_GetIter (seq);
84+ size_t count {0 };
85+ if (it)
86+ {
87+ PyObject* item {nullptr };
88+ while ((item = PyIter_Next (it)) && count < 16 )
89+ {
90+ long val = PyLong_AsLong (item);
91+ Py_DECREF (item);
92+ if (val == -1 && PyErr_Occurred ())
93+ {
94+ delete self;
95+ self = nullptr ;
96+ PyErr_SetString (PyExc_TypeError, " Sequence must contain integers" );
97+ break ;
98+ }
99+ else if (val < 0 || val > 255 )
100+ {
101+ delete self;
102+ self = nullptr ;
103+ PyErr_SetString (PyExc_ValueError, " Each value must be in 0..255" );
104+ break ;
105+ }
106+
107+ (*self)[count] = static_cast <uint8_t >(val);
108+ ++count;
109+ }
110+ Py_DECREF (it);
111+ if ((nullptr != item || count != 16 ) && nullptr != self)
112+ {
113+ delete self;
114+ self = nullptr ;
115+ PyErr_SetString (PyExc_ValueError, " Expected 16 elements" );
116+ }
117+ }
118+ else
119+ {
120+ delete self;
121+ self = nullptr ;
122+ PyErr_SetString (PyExc_TypeError, " Expected a sequence of 16 integers (0..255) or 16-byte object" );
123+ }
124+ }
125+
126+ SWIG_PYTHON_THREAD_END_BLOCK;
127+
128+ return self;
59129 }
60- }
61130
62- %typemap(out) eprosima::fastdds::rtps::InstanceHandleValue_t*
63- {
64- constexpr size_t ih_size = std::tuple_size<eprosima::fastdds::rtps::KeyHash_t>::value;
65- PyObject* python_tuple = PyTuple_New (ih_size);
131+ size_t __len__ () const { return 16 ; }
66132
67- if (python_tuple)
68- {
69- for (size_t count = 0 ; count < ih_size; ++count)
70- {
71- PyTuple_SetItem (python_tuple, count, PyInt_FromLong ((*$1 )[count]));
72- }
133+ uint8_t __getitem__ (size_t i) const {
134+ if (i >= 16 ) throw std::out_of_range (" index out of range" );
135+ return $self->operator [](i);
73136 }
74137
75- $result = python_tuple;
138+ void __setitem__ (size_t i, uint8_t v) {
139+ if (i >= 16 ) throw std::out_of_range (" index out of range" );
140+ $self->operator [](i) = v;
141+ }
76142}
77143
78- // Template for std::vector<InstanceHandle_t>
79- %template (InstanceHandleVector) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>;
80- %typemap(doctype) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>" InstanceHandleVector" ;
81-
82- %include " fastdds/rtps/common/InstanceHandle.hpp"
144+ %ignore eprosima::fastdds::rtps::InstanceHandle_t::value;
83145
84146// Declare the comparison operators as internal to the class
85147%extend eprosima::fastdds::rtps::InstanceHandle_t {
@@ -106,4 +168,51 @@ long hash(const eprosima::fastdds::rtps::InstanceHandle_t& handle)
106168 {
107169 return hash (*$self);
108170 }
171+
172+ // Setter from sequence (tuple/list/bytes/bytearray)
173+ void from_sequence (PyObject* seq) {
174+ // Reuse the constructor to validate and copy
175+ eprosima::fastdds::rtps::InstanceHandleValue_t* tmp = new_eprosima_fastdds_rtps_InstanceHandleValue_t (seq);
176+ if (nullptr != tmp)
177+ {
178+ for (int i = 0 ; i < 16 ; ++i) $self->value [i] = (*tmp)[i];
179+ delete tmp; // avoid memory leak
180+ }
181+ }
182+
183+ // Getter: return a tuple of 16 ints (0..255)
184+ PyObject* to_sequence () const {
185+ SWIG_PYTHON_THREAD_BEGIN_BLOCK;
186+
187+ PyObject* python_tuple = PyTuple_New (16 );
188+
189+ if (python_tuple)
190+ {
191+ for (size_t count = 0 ; count < 16 ; ++count)
192+ {
193+ PyTuple_SetItem (python_tuple, count, PyInt_FromLong ($self->value [count]));
194+ }
195+ }
196+
197+ SWIG_PYTHON_THREAD_END_BLOCK;
198+
199+ return python_tuple;
200+ }
109201}
202+
203+ // Template for std::vector<InstanceHandle_t>
204+ %template (InstanceHandleVector) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>;
205+ %typemap(doctype) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>" InstanceHandleVector" ;
206+
207+ %include " fastdds/rtps/common/InstanceHandle.hpp"
208+
209+ %pythoncode %{
210+ def _ihv_get_value (self):
211+ return self.to_sequence ()
212+
213+ def _ihv_set_value (self, seq):
214+ self.from_sequence (seq)
215+
216+ InstanceHandle_t.value = property (_ihv_get_value, _ihv_set_value,
217+ doc=" 16-byte value as list/tuple/bytes/bytearray" )
218+ %}
0 commit comments