Skip to content

Commit f6d710e

Browse files
Маслов Александр АлександровичEsipovPA
authored andcommitted
Serialization uses C struct members of message
Signed-off-by: Маслов Александр Александрович <aamaslov@sberautotech.ru>
1 parent b9289df commit f6d710e

File tree

1 file changed

+23
-102
lines changed

1 file changed

+23
-102
lines changed

rosidl_generator_py/resource/_msg_support.c.em

Lines changed: 23 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -191,44 +191,33 @@ for member in message.structure.members:
191191
elif isinstance(member.type, AbstractSequence) and 'array.array' not in lazy_import_methods:
192192
lazy_import_methods.add('array.array')
193193
TEMPLATE('_import_type.c.em', full_type_name='array.array', func_name='lazy_import_array')
194-
}@
195-
@{
194+
196195
module_name = '_' + convert_camel_case_to_lower_case_underscore(interface_path.stem)
197196
class_module = '%s.%s' % ('.'.join(message.structure.namespaced_type.namespaces), module_name)
198197
namespaced_type = message.structure.namespaced_type.name
198+
full_type_name = '.'.join(message.structure.namespaced_type.namespaces + [module_name, message.structure.namespaced_type.name])
199+
import_func_name = 'lazy_import_' + convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name)
200+
no_fields = len(message.structure.members) == 1 and message.structure.members[0].name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME
201+
TEMPLATE(
202+
'_import_type.c.em',
203+
full_type_name=full_type_name, func_name=import_func_name, ensure_is_type=True)
199204
}@
200205
ROSIDL_GENERATOR_C_EXPORT
201206
bool @('__'.join(message.structure.namespaced_type.namespaces + [convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name)]))__convert_from_py(PyObject * _pymsg, void * _ros_message)
202207
{
203208
// check that the passed message is of the expected Python class
204209
{
205-
PyObject * class_attr = PyObject_GetAttrString(_pymsg, "__class__");
206-
if (class_attr == NULL) {
207-
return false;
208-
}
209-
PyObject * name_attr = PyObject_GetAttrString(class_attr, "__name__");
210-
if (name_attr == NULL) {
211-
Py_DECREF(class_attr);
212-
return false;
213-
}
214-
PyObject * module_attr = PyObject_GetAttrString(class_attr, "__module__");
215-
if (module_attr == NULL) {
216-
Py_DECREF(name_attr);
217-
Py_DECREF(class_attr);
218-
return false;
219-
}
220-
221-
// PyUnicode_1BYTE_DATA is just a cast
222-
assert(strncmp("@(class_module)", (char *)PyUnicode_1BYTE_DATA(module_attr), @(len(class_module))) == 0);
223-
assert(strncmp("@(namespaced_type)", (char *)PyUnicode_1BYTE_DATA(name_attr), @(len(namespaced_type))) == 0);
224-
225-
Py_DECREF(module_attr);
226-
Py_DECREF(name_attr);
227-
Py_DECREF(class_attr);
210+
PyTypeObject * py_type = (PyTypeObject *)@(import_func_name)();
211+
assert(Py_TYPE(_pymsg) == py_type);
228212
}
229213
@(msg_typename) * ros_message = _ros_message;
214+
@[if no_fields]@
215+
ros_message->@(member.name) = 0;
216+
@[else]
217+
@(message.structure.namespaced_type.name)Base * base_msg = (@(message.structure.namespaced_type.name)Base *)_pymsg;
218+
@[end if]@
230219
@[for member in message.structure.members]@
231-
@[ if len(message.structure.members) == 1 and member.name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
220+
@[ if no_fields]@
232221
ros_message->@(member.name) = 0;
233222
@[ continue]@
234223
@[ end if]@
@@ -238,31 +227,30 @@ if isinstance(type_, AbstractNestedType):
238227
type_ = type_.value_type
239228
}@
240229
{ // @(member.name)
241-
PyObject * field = PyObject_GetAttrString(_pymsg, "@(member.name)");
230+
@[ if not isinstance(member.type, BasicType)]@
231+
PyObject * field = base_msg->_@(member.name);
242232
if (!field) {
243233
return false;
244234
}
235+
@[ end if]@
245236
@[ if isinstance(type_, NamespacedType)]@
246237
@{
247238
nested_type = '__'.join(type_.namespaced_name())
248239
}@
249240
@[ if isinstance(member.type, AbstractNestedType)]@
250241
PyObject * seq_field = PySequence_Fast(field, "expected a sequence in '@(member.name)'");
251242
if (!seq_field) {
252-
Py_DECREF(field);
253243
return false;
254244
}
255245
@[ if isinstance(member.type, AbstractSequence)]@
256246
Py_ssize_t size = PySequence_Size(field);
257247
if (-1 == size) {
258248
Py_DECREF(seq_field);
259-
Py_DECREF(field);
260249
return false;
261250
}
262251
if (!@(nested_type)__Sequence__init(&(ros_message->@(member.name)), size)) {
263252
PyErr_SetString(PyExc_RuntimeError, "unable to create @(nested_type)__Sequence ros_message");
264253
Py_DECREF(seq_field);
265-
Py_DECREF(field);
266254
return false;
267255
}
268256
@(nested_type) * dest = ros_message->@(member.name).data;
@@ -273,14 +261,12 @@ nested_type = '__'.join(type_.namespaced_name())
273261
for (Py_ssize_t i = 0; i < size; ++i) {
274262
if (!@('__'.join(type_.namespaces + [convert_camel_case_to_lower_case_underscore(type_.name)]))__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) {
275263
Py_DECREF(seq_field);
276-
Py_DECREF(field);
277264
return false;
278265
}
279266
}
280267
Py_DECREF(seq_field);
281268
@[ else]@
282269
if (!@('__'.join(type_.namespaces + [convert_camel_case_to_lower_case_underscore(type_.name)]))__convert_from_py(field, &ros_message->@(member.name))) {
283-
Py_DECREF(field);
284270
return false;
285271
}
286272
@[ end if]@
@@ -291,21 +277,18 @@ nested_type = '__'.join(type_.namespaced_name())
291277
Py_buffer view;
292278
int rc = PyObject_GetBuffer(field, &view, PyBUF_SIMPLE);
293279
if (rc < 0) {
294-
Py_DECREF(field);
295280
return false;
296281
}
297282
Py_ssize_t size = view.len / sizeof(@primitive_msg_type_to_c(member.type.value_type));
298283
if (!rosidl_runtime_c__@(member.type.value_type.typename)__Sequence__init(&(ros_message->@(member.name)), size)) {
299284
PyErr_SetString(PyExc_RuntimeError, "unable to create @(member.type.value_type.typename)__Sequence ros_message");
300285
PyBuffer_Release(&view);
301-
Py_DECREF(field);
302286
return false;
303287
}
304288
@primitive_msg_type_to_c(member.type.value_type) * dest = ros_message->@(member.name).data;
305289
rc = PyBuffer_ToContiguous(dest, &view, view.len, 'C');
306290
if (rc < 0) {
307291
PyBuffer_Release(&view);
308-
Py_DECREF(field);
309292
return false;
310293
}
311294
PyBuffer_Release(&view);
@@ -325,36 +308,31 @@ nested_type = '__'.join(type_.namespaced_name())
325308
@[ else]@
326309
PyObject * seq_field = PySequence_Fast(field, "expected a sequence in '@(member.name)'");
327310
if (!seq_field) {
328-
Py_DECREF(field);
329311
return false;
330312
}
331313
@[ end if]@
332314
@[ if isinstance(member.type, AbstractSequence)]@
333315
Py_ssize_t size = PySequence_Size(field);
334316
if (-1 == size) {
335317
Py_DECREF(seq_field);
336-
Py_DECREF(field);
337318
return false;
338319
}
339320
@[ if isinstance(member.type.value_type, AbstractString)]@
340321
if (!rosidl_runtime_c__String__Sequence__init(&(ros_message->@(member.name)), size)) {
341322
PyErr_SetString(PyExc_RuntimeError, "unable to create String__Sequence ros_message");
342323
Py_DECREF(seq_field);
343-
Py_DECREF(field);
344324
return false;
345325
}
346326
@[ elif isinstance(member.type.value_type, AbstractWString)]@
347327
if (!rosidl_runtime_c__U16String__Sequence__init(&(ros_message->@(member.name)), size)) {
348328
PyErr_SetString(PyExc_RuntimeError, "unable to create U16String__Sequence ros_message");
349329
Py_DECREF(seq_field);
350-
Py_DECREF(field);
351330
return false;
352331
}
353332
@[ else]@
354333
if (!rosidl_runtime_c__@(member.type.value_type.typename)__Sequence__init(&(ros_message->@(member.name)), size)) {
355334
PyErr_SetString(PyExc_RuntimeError, "unable to create @(member.type.value_type.typename)__Sequence ros_message");
356335
Py_DECREF(seq_field);
357-
Py_DECREF(field);
358336
return false;
359337
}
360338
@[ end if]@
@@ -368,7 +346,6 @@ nested_type = '__'.join(type_.namespaced_name())
368346
PyObject * item = PySequence_Fast_GET_ITEM(seq_field, i);
369347
if (!item) {
370348
Py_DECREF(seq_field);
371-
Py_DECREF(field);
372349
return false;
373350
}
374351
@[ end if]@
@@ -392,7 +369,6 @@ nested_type = '__'.join(type_.namespaced_name())
392369
PyObject * encoded_item = PyUnicode_AsUTF8String(item);
393370
if (!encoded_item) {
394371
Py_DECREF(seq_field);
395-
Py_DECREF(field);
396372
return false;
397373
}
398374
rosidl_runtime_c__String__assign(&dest[i], PyBytes_AS_STRING(encoded_item));
@@ -403,7 +379,6 @@ nested_type = '__'.join(type_.namespaced_name())
403379
PyObject * encoded_item = PyUnicode_AsUTF16String(item);
404380
if (!encoded_item) {
405381
Py_DECREF(seq_field);
406-
Py_DECREF(field);
407382
return false;
408383
}
409384
char * buffer;
@@ -412,15 +387,13 @@ nested_type = '__'.join(type_.namespaced_name())
412387
if (rc) {
413388
Py_DECREF(encoded_item);
414389
Py_DECREF(seq_field);
415-
Py_DECREF(field);
416390
return false;
417391
}
418392
// use offset of 2 to skip BOM mark
419393
bool succeeded = rosidl_runtime_c__U16String__assignn_from_char(&dest[i], buffer + 2, length - 2);
420394
Py_DECREF(encoded_item);
421395
if (!succeeded) {
422396
Py_DECREF(seq_field);
423-
Py_DECREF(field);
424397
return false;
425398
}
426399
@[ elif isinstance(member.type.value_type, BasicType) and member.type.value_type.typename == 'boolean']@
@@ -464,18 +437,6 @@ nested_type = '__'.join(type_.namespaced_name())
464437
}
465438
Py_DECREF(seq_field);
466439
}
467-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'char']@
468-
assert(PyUnicode_Check(field));
469-
PyObject * encoded_field = PyUnicode_AsUTF8String(field);
470-
if (!encoded_field) {
471-
Py_DECREF(field);
472-
return false;
473-
}
474-
ros_message->@(member.name) = PyBytes_AS_STRING(encoded_field)[0];
475-
Py_DECREF(encoded_field);
476-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'octet']@
477-
assert(PyBytes_Check(field));
478-
ros_message->@(member.name) = PyBytes_AS_STRING(field)[0];
479440
@[ elif isinstance(member.type, AbstractString)]@
480441
assert(PyUnicode_Check(field));
481442
PyObject * encoded_field = PyUnicode_AsUTF8String(field);
@@ -490,78 +451,38 @@ nested_type = '__'.join(type_.namespaced_name())
490451
// the returned string starts with a BOM mark and uses native byte order
491452
PyObject * encoded_field = PyUnicode_AsUTF16String(field);
492453
if (!encoded_field) {
493-
Py_DECREF(field);
494454
return false;
495455
}
496456
char * buffer;
497457
Py_ssize_t length;
498458
int rc = PyBytes_AsStringAndSize(encoded_field, &buffer, &length);
499459
if (rc) {
500460
Py_DECREF(encoded_field);
501-
Py_DECREF(field);
502461
return false;
503462
}
504463
// use offset of 2 to skip BOM mark
505464
{
506465
bool succeeded = rosidl_runtime_c__U16String__assignn_from_char(&ros_message->@(member.name), buffer + 2, length - 2);
507466
Py_DECREF(encoded_field);
508467
if (!succeeded) {
509-
Py_DECREF(field);
510468
return false;
511469
}
512470
}
513-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'boolean']@
514-
assert(PyBool_Check(field));
515-
ros_message->@(member.name) = (Py_True == field);
516-
@[ elif isinstance(member.type, BasicType) and member.type.typename in ('float', 'double')]@
517-
assert(PyFloat_Check(field));
471+
@[ elif isinstance(member.type, BasicType)]@
518472
@[ if member.type.typename == 'float']@
519-
ros_message->@(member.name) = (float)PyFloat_AS_DOUBLE(field);
520-
@[ else]@
521-
ros_message->@(member.name) = PyFloat_AS_DOUBLE(field);
522-
@[ end if]@
523-
@[ elif isinstance(member.type, BasicType) and member.type.typename in (
524-
'int8',
525-
'int16',
526-
'int32',
527-
)]@
528-
assert(PyLong_Check(field));
529-
ros_message->@(member.name) = (@(primitive_msg_type_to_c(member.type)))PyLong_AsLong(field);
530-
@[ elif isinstance(member.type, BasicType) and member.type.typename in (
531-
'uint8',
532-
'uint16',
533-
'uint32',
534-
)]@
535-
assert(PyLong_Check(field));
536-
@[ if member.type.typename == 'uint32']@
537-
ros_message->@(member.name) = PyLong_AsUnsignedLong(field);
473+
ros_message->@(member.name) = (float)base_msg->_@(member.name);
538474
@[ else]@
539-
ros_message->@(member.name) = (@(primitive_msg_type_to_c(member.type)))PyLong_AsUnsignedLong(field);
475+
ros_message->@(member.name) = base_msg->_@(member.name);
540476
@[ end if]@
541-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'int64']@
542-
assert(PyLong_Check(field));
543-
ros_message->@(member.name) = PyLong_AsLongLong(field);
544-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'uint64']@
545-
assert(PyLong_Check(field));
546-
ros_message->@(member.name) = PyLong_AsUnsignedLongLong(field);
547477
@[ else]@
548478
assert(false);
549479
@[ end if]@
550-
Py_DECREF(field);
551480
}
552481
@[end for]@
553482

554483
return true;
555484
}
556485

557-
@{
558-
full_type_name = '.'.join(message.structure.namespaced_type.namespaces + [module_name, message.structure.namespaced_type.name])
559-
import_func_name = 'lazy_import_' + convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name)
560-
TEMPLATE(
561-
'_import_type.c.em',
562-
full_type_name=full_type_name, func_name=import_func_name, ensure_is_type=True)
563-
}@
564-
565486
ROSIDL_GENERATOR_C_EXPORT
566487
PyObject * @('__'.join(message.structure.namespaced_type.namespaces + [convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name)]))__convert_to_py(void * raw_ros_message)
567488
{
@@ -587,13 +508,13 @@ PyObject * @('__'.join(message.structure.namespaced_type.namespaces + [convert_c
587508
return NULL;
588509
}
589510
}
590-
@[if len(message.structure.members) == 1 and member.name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
511+
@[if no_fields]@
591512
(void)raw_ros_message;
592513
@[else]@
593514
@(msg_typename) * ros_message = (@(msg_typename) *)raw_ros_message;
594515
@[end if]@
595516
@[for member in message.structure.members]@
596-
@[ if len(message.structure.members) == 1 and member.name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
517+
@[ if no_fields]@
597518
@[ continue]@
598519
@[ end if]@
599520
@{

0 commit comments

Comments
 (0)