Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions fastdds_python/src/swig/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set(${PROJECT_NAME}_MODULE
set(${PROJECT_NAME}_FILE
${CMAKE_CURRENT_BINARY_DIR}/${${PROJECT_NAME}_MODULE}.i
)
set_property(SOURCE ${${PROJECT_NAME}_FILE} PROPERTY USE_SWIG_DEPENDENCIES TRUE)

file(GENERATE
OUTPUT ${${PROJECT_NAME}_FILE}
Expand Down
2 changes: 2 additions & 0 deletions fastdds_python/src/swig/fastdds/dds/core/Time_t.i
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
%ignore eprosima::fastdds::dds::operator+(const Time_t&, const Time_t&);
%ignore eprosima::fastdds::dds::operator-(const Time_t&, const Time_t&);

%ignore eprosima::fastdds::dds::Time_t::is_infinite(const Time_t&);

// Declare the comparison operators as internal to the class
%extend eprosima::fastdds::dds::Time_t {
bool operator==(const eprosima::fastdds::dds::Time_t& other) const
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// Ignore overloaded constructor and methods that have no effect on target language
%copyctor eprosima::fastdds::rtps::BinaryProperty;
%ignore eprosima::fastdds::rtps::BinaryProperty::BinaryProperty(BinaryProperty&&);
%ignore eprosima::fastdds::rtps::BinaryProperty::name(std::string &&);
%ignore eprosima::fastdds::rtps::BinaryProperty::value(std::vector<uint8_t> &&);
%ignore eprosima::fastdds::rtps::BinaryProperty::propagate() const;
Expand Down
183 changes: 146 additions & 37 deletions fastdds_python/src/swig/fastdds/rtps/common/InstanceHandle.i
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
// limitations under the License.

%{
#include <stdexcept>
#include <vector>

#include "fastdds/rtps/common/InstanceHandle.hpp"

// Define a hash method in global scope for InstanceHandle_t types
Expand All @@ -26,60 +29,119 @@ long hash(const eprosima::fastdds::rtps::InstanceHandle_t& handle)
}
return ret;
}

%}

// SWIG does not support type conversion operators correctly unless converted to a normal method
%rename(get_guid) eprosima::fastdds::rtps::InstanceHandle_t::operator const GUID_t&;

%ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator [] const;
%ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator [];
%ignore eprosima::fastdds::rtps::operator <<(std::ostream&, const InstanceHandle_t&);
%ignore eprosima::fastdds::rtps::operator >>(std::istream&, InstanceHandle_t&);
%rename(read_pointer_cast) eprosima::fastdds::rtps::InstanceHandleValue_t::operator const octet* () const;
%rename(write_pointer_cast) eprosima::fastdds::rtps::InstanceHandleValue_t::operator octet* ();

%typemap(in) eprosima::fastdds::rtps::InstanceHandleValue_t*(eprosima::fastdds::rtps::InstanceHandleValue_t temp)
{
if (PyTuple_Check($input))
{
eprosima::fastdds::rtps::octet* buf = temp;
if (!PyArg_ParseTuple($input, "BBBBBBBBBBBBBBBB",
buf, buf+1, buf+2, buf+3, buf+4, buf+5, buf+6, buf+7, buf+8,
buf+9, buf+10, buf+11, buf+12, buf+13, buf+14, buf+15))
%ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator const octet* () const;
%ignore eprosima::fastdds::rtps::InstanceHandleValue_t::operator octet* ();

%extend eprosima::fastdds::rtps::InstanceHandleValue_t {

// Constructor from a sequence of 16 bytes (tuple/list/bytes/bytearray)
InstanceHandleValue_t(PyObject* seq) {
eprosima::fastdds::rtps::InstanceHandleValue_t* self = new eprosima::fastdds::rtps::InstanceHandleValue_t();
SWIG_PYTHON_THREAD_BEGIN_BLOCK;

// Fast-path: bytes
if (PyBytes_Check(seq)) {
if (PyBytes_GET_SIZE(seq) == 16)
{
const char* b = PyBytes_AS_STRING(seq);
for (int i = 0; i < 16; ++i) (*self)[i] = (uint8_t)(unsigned char)b[i];
}
else
{
delete self;
self = nullptr;
PyErr_SetString(PyExc_ValueError, "Expected 16 bytes");
}
}
// Fast-path: bytearray
else if (PyByteArray_Check(seq))
{
PyErr_SetString(PyExc_TypeError, "tuple must have 16 elements");
SWIG_fail;
if (PyByteArray_GET_SIZE(seq) == 16)
{
const char* b = PyByteArray_AS_STRING(seq);
for (int i = 0; i < 16; ++i) (*self)[i] = (uint8_t)(unsigned char)b[i];
}
else
{
delete self;
self = nullptr;
PyErr_SetString(PyExc_ValueError, "Expected 16 bytes");
}
}
$1 = &temp;
}
else
{
PyErr_SetString(PyExc_TypeError, "expected a tuple.");
SWIG_fail;
else
{
// Generic fallback: iterable from 16 ints 0..255
PyObject* it = PyObject_GetIter(seq);
size_t count {0};
if (it)
{
PyObject* item {nullptr};
while ((item = PyIter_Next(it)) && count < 16)
{
long val = PyLong_AsLong(item);
Py_DECREF(item);
if (val == -1 && PyErr_Occurred())
{
delete self;
self = nullptr;
PyErr_SetString(PyExc_TypeError, "Sequence must contain integers");
break;
}
else if (val < 0 || val > 255)
{
delete self;
self = nullptr;
PyErr_SetString(PyExc_ValueError, "Each value must be in 0..255");
break;
}

(*self)[count] = static_cast<uint8_t>(val);
++count;
}
Py_DECREF(it);
if ((nullptr != item || count != 16) && nullptr != self)
{
delete self;
self = nullptr;
PyErr_SetString(PyExc_ValueError, "Expected 16 elements");
}
}
else
{
delete self;
self = nullptr;
PyErr_SetString(PyExc_TypeError, "Expected a sequence of 16 integers (0..255) or 16-byte object");
}
}

SWIG_PYTHON_THREAD_END_BLOCK;

return self;
}
}

%typemap(out) eprosima::fastdds::rtps::InstanceHandleValue_t*
{
constexpr size_t ih_size = std::tuple_size<eprosima::fastdds::rtps::KeyHash_t>::value;
PyObject* python_tuple = PyTuple_New(ih_size);
size_t __len__() const { return 16; }

if (python_tuple)
{
for(size_t count = 0; count < ih_size; ++count)
{
PyTuple_SetItem(python_tuple, count, PyInt_FromLong((*$1)[count]));
}
uint8_t __getitem__(size_t i) const {
if (i >= 16) throw std::out_of_range("index out of range");
return $self->operator[](i);
}

$result = python_tuple;
void __setitem__(size_t i, uint8_t v) {
if (i >= 16) throw std::out_of_range("index out of range");
$self->operator[](i) = v;
}
}

// Template for std::vector<InstanceHandle_t>
%template(InstanceHandleVector) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>;
%typemap(doctype) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>"InstanceHandleVector";

%include "fastdds/rtps/common/InstanceHandle.hpp"
%ignore eprosima::fastdds::rtps::InstanceHandle_t::value;

// Declare the comparison operators as internal to the class
%extend eprosima::fastdds::rtps::InstanceHandle_t {
Expand All @@ -106,4 +168,51 @@ long hash(const eprosima::fastdds::rtps::InstanceHandle_t& handle)
{
return hash(*$self);
}

// Setter from sequence (tuple/list/bytes/bytearray)
void from_sequence(PyObject* seq) {
// Reuse the constructor to validate and copy
eprosima::fastdds::rtps::InstanceHandleValue_t* tmp = new_eprosima_fastdds_rtps_InstanceHandleValue_t(seq);
if (nullptr != tmp)
{
for (int i = 0; i < 16; ++i) $self->value[i] = (*tmp)[i];
delete tmp; // avoid memory leak
}
}

// Getter: return a tuple of 16 ints (0..255)
PyObject* to_sequence() const {
SWIG_PYTHON_THREAD_BEGIN_BLOCK;

PyObject* python_tuple = PyTuple_New(16);

if (python_tuple)
{
for(size_t count = 0; count < 16; ++count)
{
PyTuple_SetItem(python_tuple, count, PyInt_FromLong($self->value[count]));
}
}

SWIG_PYTHON_THREAD_END_BLOCK;

return python_tuple;
}
}

// Template for std::vector<InstanceHandle_t>
%template(InstanceHandleVector) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>;
%typemap(doctype) std::vector<eprosima::fastdds::rtps::InstanceHandle_t>"InstanceHandleVector";

%include "fastdds/rtps/common/InstanceHandle.hpp"

%pythoncode %{
def _ihv_get_value(self):
return self.to_sequence()

def _ihv_set_value(self, seq):
self.from_sequence(seq)

InstanceHandle_t.value = property(_ihv_get_value, _ihv_set_value,
doc="16-byte value as list/tuple/bytes/bytearray")
%}
1 change: 1 addition & 0 deletions fastdds_python/src/swig/fastdds/rtps/common/Locator.i
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// Ignore overloaded constructor and methods that have no effect on target language
%copyctor eprosima::fastdds::rtps::Locator_t;
%ignore eprosima::fastdds::rtps::Locator_t::Locator_t(Locator_t&&);
%ignore eprosima::fastdds::rtps::operator <<(std::ostream&, const Locator_t&);
%ignore eprosima::fastdds::rtps::operator >>(std::istream&, Locator_t&);
%ignore eprosima::fastdds::rtps::operator ==(const Locator_t&, const Locator_t&);
Expand Down
1 change: 1 addition & 0 deletions fastdds_python/src/swig/fastdds/rtps/common/Property.i
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

// Ignore overloaded constructor and methods that have no effect on target language
%copyctor eprosima::fastdds::rtps::Property;
%ignore eprosima::fastdds::rtps::Property::Property(Property&&);
%ignore eprosima::fastdds::rtps::Property::name(std::string &&);
%ignore eprosima::fastdds::rtps::Property::value(std::string &&);
%ignore eprosima::fastdds::rtps::Property::propagate() const;
Expand Down
11 changes: 11 additions & 0 deletions fastdds_python/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@
# Compile types
add_subdirectory(types)

# Unit tests
add_test(NAME unit_tests
COMMAND
${Python3_EXECUTABLE}
-m pytest
-vrP
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}/unittest
)

# DDS Api tests
add_test(NAME api_tests
COMMAND
${Python3_EXECUTABLE}
Expand Down
Loading