Skip to content

Commit d83a472

Browse files
author
Маслов Александр Александрович
committed
Serialization uses C struct members of message
Signed-off-by: Маслов Александр Александрович <[email protected]>
1 parent 2489c6f commit d83a472

File tree

1 file changed

+23
-105
lines changed

1 file changed

+23
-105
lines changed

rosidl_generator_py/resource/_msg_support.c.em

Lines changed: 23 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,14 @@ 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)
196+
full_type_name = '.'.join(message.structure.namespaced_type.namespaces + [module_name, message.structure.namespaced_type.name])
197+
import_func_name = 'lazy_import_' + convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name)
198+
no_fields = len(message.structure.members) == 1 and message.structure.members[0].name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME
199+
TEMPLATE(
200+
'_import_type.c.em',
201+
full_type_name=full_type_name, func_name=import_func_name, ensure_is_type=True)
197202
}@
198203
ROSIDL_GENERATOR_C_EXPORT
199204
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)
@@ -203,36 +208,17 @@ full_classname = '%s.%s.%s' % ('.'.join(message.structure.namespaced_type.namesp
203208
}@
204209
// check that the passed message is of the expected Python class
205210
{
206-
char full_classname_dest[@(len(full_classname) + 1)];
207-
{
208-
char * class_name = NULL;
209-
char * module_name = NULL;
210-
{
211-
PyObject * class_attr = PyObject_GetAttrString(_pymsg, "__class__");
212-
if (class_attr) {
213-
PyObject * name_attr = PyObject_GetAttrString(class_attr, "__name__");
214-
if (name_attr) {
215-
class_name = (char *)PyUnicode_1BYTE_DATA(name_attr);
216-
Py_DECREF(name_attr);
217-
}
218-
PyObject * module_attr = PyObject_GetAttrString(class_attr, "__module__");
219-
if (module_attr) {
220-
module_name = (char *)PyUnicode_1BYTE_DATA(module_attr);
221-
Py_DECREF(module_attr);
222-
}
223-
Py_DECREF(class_attr);
224-
}
225-
}
226-
if (!class_name || !module_name) {
227-
return false;
228-
}
229-
snprintf(full_classname_dest, sizeof(full_classname_dest), "%s.%s", module_name, class_name);
230-
}
231-
assert(strncmp("@(full_classname)", full_classname_dest, @(len(full_classname))) == 0);
211+
PyTypeObject * py_type = (PyTypeObject *)@(import_func_name)();
212+
assert(Py_TYPE(_pymsg) == py_type);
232213
}
233214
@(msg_typename) * ros_message = _ros_message;
215+
@[if no_fields]@
216+
ros_message->@(member.name) = 0;
217+
@[else]
218+
@(message.structure.namespaced_type.name)Base * base_msg = (@(message.structure.namespaced_type.name)Base *)_pymsg;
219+
@[end if]@
234220
@[for member in message.structure.members]@
235-
@[ if len(message.structure.members) == 1 and member.name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
221+
@[ if no_fields]@
236222
ros_message->@(member.name) = 0;
237223
@[ continue]@
238224
@[ end if]@
@@ -242,31 +228,30 @@ if isinstance(type_, AbstractNestedType):
242228
type_ = type_.value_type
243229
}@
244230
{ // @(member.name)
245-
PyObject * field = PyObject_GetAttrString(_pymsg, "@(member.name)");
231+
@[ if not isinstance(member.type, BasicType)]@
232+
PyObject * field = base_msg->_@(member.name);
246233
if (!field) {
247234
return false;
248235
}
236+
@[ end if]@
249237
@[ if isinstance(type_, NamespacedType)]@
250238
@{
251239
nested_type = '__'.join(type_.namespaced_name())
252240
}@
253241
@[ if isinstance(member.type, AbstractNestedType)]@
254242
PyObject * seq_field = PySequence_Fast(field, "expected a sequence in '@(member.name)'");
255243
if (!seq_field) {
256-
Py_DECREF(field);
257244
return false;
258245
}
259246
@[ if isinstance(member.type, AbstractSequence)]@
260247
Py_ssize_t size = PySequence_Size(field);
261248
if (-1 == size) {
262249
Py_DECREF(seq_field);
263-
Py_DECREF(field);
264250
return false;
265251
}
266252
if (!@(nested_type)__Sequence__init(&(ros_message->@(member.name)), size)) {
267253
PyErr_SetString(PyExc_RuntimeError, "unable to create @(nested_type)__Sequence ros_message");
268254
Py_DECREF(seq_field);
269-
Py_DECREF(field);
270255
return false;
271256
}
272257
@(nested_type) * dest = ros_message->@(member.name).data;
@@ -277,14 +262,12 @@ nested_type = '__'.join(type_.namespaced_name())
277262
for (Py_ssize_t i = 0; i < size; ++i) {
278263
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])) {
279264
Py_DECREF(seq_field);
280-
Py_DECREF(field);
281265
return false;
282266
}
283267
}
284268
Py_DECREF(seq_field);
285269
@[ else]@
286270
if (!@('__'.join(type_.namespaces + [convert_camel_case_to_lower_case_underscore(type_.name)]))__convert_from_py(field, &ros_message->@(member.name))) {
287-
Py_DECREF(field);
288271
return false;
289272
}
290273
@[ end if]@
@@ -295,21 +278,18 @@ nested_type = '__'.join(type_.namespaced_name())
295278
Py_buffer view;
296279
int rc = PyObject_GetBuffer(field, &view, PyBUF_SIMPLE);
297280
if (rc < 0) {
298-
Py_DECREF(field);
299281
return false;
300282
}
301283
Py_ssize_t size = view.len / sizeof(@primitive_msg_type_to_c(member.type.value_type));
302284
if (!rosidl_runtime_c__@(member.type.value_type.typename)__Sequence__init(&(ros_message->@(member.name)), size)) {
303285
PyErr_SetString(PyExc_RuntimeError, "unable to create @(member.type.value_type.typename)__Sequence ros_message");
304286
PyBuffer_Release(&view);
305-
Py_DECREF(field);
306287
return false;
307288
}
308289
@primitive_msg_type_to_c(member.type.value_type) * dest = ros_message->@(member.name).data;
309290
rc = PyBuffer_ToContiguous(dest, &view, view.len, 'C');
310291
if (rc < 0) {
311292
PyBuffer_Release(&view);
312-
Py_DECREF(field);
313293
return false;
314294
}
315295
PyBuffer_Release(&view);
@@ -329,36 +309,31 @@ nested_type = '__'.join(type_.namespaced_name())
329309
@[ else]@
330310
PyObject * seq_field = PySequence_Fast(field, "expected a sequence in '@(member.name)'");
331311
if (!seq_field) {
332-
Py_DECREF(field);
333312
return false;
334313
}
335314
@[ end if]@
336315
@[ if isinstance(member.type, AbstractSequence)]@
337316
Py_ssize_t size = PySequence_Size(field);
338317
if (-1 == size) {
339318
Py_DECREF(seq_field);
340-
Py_DECREF(field);
341319
return false;
342320
}
343321
@[ if isinstance(member.type.value_type, AbstractString)]@
344322
if (!rosidl_runtime_c__String__Sequence__init(&(ros_message->@(member.name)), size)) {
345323
PyErr_SetString(PyExc_RuntimeError, "unable to create String__Sequence ros_message");
346324
Py_DECREF(seq_field);
347-
Py_DECREF(field);
348325
return false;
349326
}
350327
@[ elif isinstance(member.type.value_type, AbstractWString)]@
351328
if (!rosidl_runtime_c__U16String__Sequence__init(&(ros_message->@(member.name)), size)) {
352329
PyErr_SetString(PyExc_RuntimeError, "unable to create U16String__Sequence ros_message");
353330
Py_DECREF(seq_field);
354-
Py_DECREF(field);
355331
return false;
356332
}
357333
@[ else]@
358334
if (!rosidl_runtime_c__@(member.type.value_type.typename)__Sequence__init(&(ros_message->@(member.name)), size)) {
359335
PyErr_SetString(PyExc_RuntimeError, "unable to create @(member.type.value_type.typename)__Sequence ros_message");
360336
Py_DECREF(seq_field);
361-
Py_DECREF(field);
362337
return false;
363338
}
364339
@[ end if]@
@@ -372,7 +347,6 @@ nested_type = '__'.join(type_.namespaced_name())
372347
PyObject * item = PySequence_Fast_GET_ITEM(seq_field, i);
373348
if (!item) {
374349
Py_DECREF(seq_field);
375-
Py_DECREF(field);
376350
return false;
377351
}
378352
@[ end if]@
@@ -396,7 +370,6 @@ nested_type = '__'.join(type_.namespaced_name())
396370
PyObject * encoded_item = PyUnicode_AsUTF8String(item);
397371
if (!encoded_item) {
398372
Py_DECREF(seq_field);
399-
Py_DECREF(field);
400373
return false;
401374
}
402375
rosidl_runtime_c__String__assign(&dest[i], PyBytes_AS_STRING(encoded_item));
@@ -407,7 +380,6 @@ nested_type = '__'.join(type_.namespaced_name())
407380
PyObject * encoded_item = PyUnicode_AsUTF16String(item);
408381
if (!encoded_item) {
409382
Py_DECREF(seq_field);
410-
Py_DECREF(field);
411383
return false;
412384
}
413385
char * buffer;
@@ -416,15 +388,13 @@ nested_type = '__'.join(type_.namespaced_name())
416388
if (rc) {
417389
Py_DECREF(encoded_item);
418390
Py_DECREF(seq_field);
419-
Py_DECREF(field);
420391
return false;
421392
}
422393
// use offset of 2 to skip BOM mark
423394
bool succeeded = rosidl_runtime_c__U16String__assignn_from_char(&dest[i], buffer + 2, length - 2);
424395
Py_DECREF(encoded_item);
425396
if (!succeeded) {
426397
Py_DECREF(seq_field);
427-
Py_DECREF(field);
428398
return false;
429399
}
430400
@[ elif isinstance(member.type.value_type, BasicType) and member.type.value_type.typename == 'boolean']@
@@ -468,18 +438,6 @@ nested_type = '__'.join(type_.namespaced_name())
468438
}
469439
Py_DECREF(seq_field);
470440
}
471-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'char']@
472-
assert(PyUnicode_Check(field));
473-
PyObject * encoded_field = PyUnicode_AsUTF8String(field);
474-
if (!encoded_field) {
475-
Py_DECREF(field);
476-
return false;
477-
}
478-
ros_message->@(member.name) = PyBytes_AS_STRING(encoded_field)[0];
479-
Py_DECREF(encoded_field);
480-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'octet']@
481-
assert(PyBytes_Check(field));
482-
ros_message->@(member.name) = PyBytes_AS_STRING(field)[0];
483441
@[ elif isinstance(member.type, AbstractString)]@
484442
assert(PyUnicode_Check(field));
485443
PyObject * encoded_field = PyUnicode_AsUTF8String(field);
@@ -494,78 +452,38 @@ nested_type = '__'.join(type_.namespaced_name())
494452
// the returned string starts with a BOM mark and uses native byte order
495453
PyObject * encoded_field = PyUnicode_AsUTF16String(field);
496454
if (!encoded_field) {
497-
Py_DECREF(field);
498455
return false;
499456
}
500457
char * buffer;
501458
Py_ssize_t length;
502459
int rc = PyBytes_AsStringAndSize(encoded_field, &buffer, &length);
503460
if (rc) {
504461
Py_DECREF(encoded_field);
505-
Py_DECREF(field);
506462
return false;
507463
}
508464
// use offset of 2 to skip BOM mark
509465
{
510466
bool succeeded = rosidl_runtime_c__U16String__assignn_from_char(&ros_message->@(member.name), buffer + 2, length - 2);
511467
Py_DECREF(encoded_field);
512468
if (!succeeded) {
513-
Py_DECREF(field);
514469
return false;
515470
}
516471
}
517-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'boolean']@
518-
assert(PyBool_Check(field));
519-
ros_message->@(member.name) = (Py_True == field);
520-
@[ elif isinstance(member.type, BasicType) and member.type.typename in ('float', 'double')]@
521-
assert(PyFloat_Check(field));
472+
@[ elif isinstance(member.type, BasicType)]@
522473
@[ if member.type.typename == 'float']@
523-
ros_message->@(member.name) = (float)PyFloat_AS_DOUBLE(field);
474+
ros_message->@(member.name) = (float)base_msg->_@(member.name);
524475
@[ else]@
525-
ros_message->@(member.name) = PyFloat_AS_DOUBLE(field);
476+
ros_message->@(member.name) = base_msg->_@(member.name);
526477
@[ end if]@
527-
@[ elif isinstance(member.type, BasicType) and member.type.typename in (
528-
'int8',
529-
'int16',
530-
'int32',
531-
)]@
532-
assert(PyLong_Check(field));
533-
ros_message->@(member.name) = (@(primitive_msg_type_to_c(member.type)))PyLong_AsLong(field);
534-
@[ elif isinstance(member.type, BasicType) and member.type.typename in (
535-
'uint8',
536-
'uint16',
537-
'uint32',
538-
)]@
539-
assert(PyLong_Check(field));
540-
@[ if member.type.typename == 'uint32']@
541-
ros_message->@(member.name) = PyLong_AsUnsignedLong(field);
542-
@[ else]@
543-
ros_message->@(member.name) = (@(primitive_msg_type_to_c(member.type)))PyLong_AsUnsignedLong(field);
544-
@[ end if]@
545-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'int64']@
546-
assert(PyLong_Check(field));
547-
ros_message->@(member.name) = PyLong_AsLongLong(field);
548-
@[ elif isinstance(member.type, BasicType) and member.type.typename == 'uint64']@
549-
assert(PyLong_Check(field));
550-
ros_message->@(member.name) = PyLong_AsUnsignedLongLong(field);
551478
@[ else]@
552479
assert(false);
553480
@[ end if]@
554-
Py_DECREF(field);
555481
}
556482
@[end for]@
557483

558484
return true;
559485
}
560486

561-
@{
562-
full_type_name = '.'.join(message.structure.namespaced_type.namespaces + [module_name, message.structure.namespaced_type.name])
563-
import_func_name = 'lazy_import_' + convert_camel_case_to_lower_case_underscore(message.structure.namespaced_type.name)
564-
TEMPLATE(
565-
'_import_type.c.em',
566-
full_type_name=full_type_name, func_name=import_func_name, ensure_is_type=True)
567-
}@
568-
569487
ROSIDL_GENERATOR_C_EXPORT
570488
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)
571489
{
@@ -591,13 +509,13 @@ PyObject * @('__'.join(message.structure.namespaced_type.namespaces + [convert_c
591509
return NULL;
592510
}
593511
}
594-
@[if len(message.structure.members) == 1 and member.name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
512+
@[if no_fields]@
595513
(void)raw_ros_message;
596514
@[else]@
597515
@(msg_typename) * ros_message = (@(msg_typename) *)raw_ros_message;
598516
@[end if]@
599517
@[for member in message.structure.members]@
600-
@[ if len(message.structure.members) == 1 and member.name == EMPTY_STRUCTURE_REQUIRED_MEMBER_NAME]@
518+
@[ if no_fields]@
601519
@[ continue]@
602520
@[ end if]@
603521
@{

0 commit comments

Comments
 (0)