From c2763f3c1eaefddf08be88b8c34188456e25643a Mon Sep 17 00:00:00 2001 From: Martins Mozeiko Date: Wed, 8 Aug 2018 17:17:23 -0700 Subject: [PATCH 01/12] Call conversion functions directly This makes generated convert to and from function to call C functions direclty instead of going through Python capsule API. Conversion functions are placed in separate libraries that link to each other. Python module libraries links to these new libraries. See #9 for more details. --- ...idl_generator_py_generate_interfaces.cmake | 62 +++++++++-- .../_msg_pkg_typesupport_entry_point.c.em | 38 +++++-- .../resource/_msg_support.c.em | 105 +++++------------- 3 files changed, 111 insertions(+), 94 deletions(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index 01d5a218..93f83a7d 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -192,14 +192,24 @@ macro(set_properties _build_type) SUFFIX "${PythonExtra_EXTENSION_EXTENSION}") endmacro() +macro(set_lib_properties _build_type) + set_target_properties(${_target_name_lib} PROPERTIES + COMPILE_OPTIONS "${_extension_compile_flags}" + LIBRARY_OUTPUT_DIRECTORY${_build_type} ${_output_path} + RUNTIME_OUTPUT_DIRECTORY${_build_type} ${_output_path}) +endmacro() + foreach(_typesupport_impl ${_typesupport_impls}) find_package(${_typesupport_impl} REQUIRED) set(_pyext_suffix "__pyext") set(_target_name "${PROJECT_NAME}__${_typesupport_impl}${_pyext_suffix}") + set(_target_name_lib "${PROJECT_NAME}__python_${_typesupport_impl}") add_library(${_target_name} SHARED ${_generated_extension_${_typesupport_impl}_files} + ) + add_library(${_target_name_lib} SHARED ${_generated_msg_c_files} ${_generated_srv_c_files} ) @@ -209,6 +219,11 @@ foreach(_typesupport_impl ${_typesupport_impls}) ${rosidl_generate_interfaces_TARGET}${_target_suffix} ${rosidl_generate_interfaces_TARGET}__rosidl_typesupport_c ) + add_dependencies( + ${_target_name_lib} + ${rosidl_generate_interfaces_TARGET}${_target_suffix} + ${rosidl_generate_interfaces_TARGET}__rosidl_typesupport_c + ) set(_extension_compile_flags "") set(_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) @@ -218,18 +233,16 @@ foreach(_typesupport_impl ${_typesupport_impls}) if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE_DEBUG}) endif() - set_properties("") - if(WIN32) - set_properties("_DEBUG") - set_properties("_MINSIZEREL") - set_properties("_RELEASE") - set_properties("_RELWITHDEBINFO") - endif() target_link_libraries( ${_target_name} + ${_target_name_lib} ${PythonExtra_LIBRARIES} ${rosidl_generate_interfaces_TARGET}__${_typesupport_impl} ) + target_link_libraries( + ${_target_name_lib} + ${PythonExtra_LIBRARIES} + ) target_include_directories(${_target_name} PUBLIC @@ -237,8 +250,14 @@ foreach(_typesupport_impl ${_typesupport_impls}) ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_py ${PythonExtra_INCLUDE_DIRS} ) + target_include_directories(${_target_name_lib} + PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c + ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_py + ${PythonExtra_INCLUDE_DIRS} + ) - rosidl_target_interfaces(${_target_name} + rosidl_target_interfaces(${_target_name_lib} ${rosidl_generate_interfaces_TARGET} rosidl_typesupport_c) ament_target_dependencies(${_target_name} @@ -250,8 +269,31 @@ foreach(_typesupport_impl ${_typesupport_impls}) ament_target_dependencies(${_target_name} ${_pkg_name} ) + + set(_pkg_base "${${_pkg_name}_DIR}/../../..") + set(_pkg_filename "${_pkg_name}__python_${_typesupport_impl}") + + if(WIN32) + target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/${_pkg_filename}.lib") + else() + target_link_libraries(${_target_name_lib} "${_pkg_base}/lib/lib${_pkg_filename}.so") + endif() + endforeach() + set_properties("") + set_lib_properties("") + if(WIN32) + set_properties("_DEBUG") + set_properties("_MINSIZEREL") + set_properties("_RELEASE") + set_properties("_RELWITHDEBINFO") + set_lib_properties("_DEBUG") + set_lib_properties("_MINSIZEREL") + set_lib_properties("_RELEASE") + set_lib_properties("_RELWITHDEBINFO") + endif() + add_dependencies(${_target_name} ${rosidl_generate_interfaces_TARGET}__${_typesupport_impl} ) @@ -265,6 +307,10 @@ foreach(_typesupport_impl ${_typesupport_impls}) if(NOT rosidl_generate_interfaces_SKIP_INSTALL) install(TARGETS ${_target_name} DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}") + install(TARGETS ${_target_name_lib} + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) endif() endforeach() diff --git a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em index a4820d6f..d5ed28b3 100644 --- a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em +++ b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em @@ -18,6 +18,12 @@ #include #include +#ifdef WIN32 +# define IMPORT_API __declspec(dllimport) +#else +# define IMPORT_API +#endif + @{ static_includes = set([ '#include ', @@ -39,7 +45,9 @@ for spec, subfolder in message_specs: type_name = spec.base_type.type module_name = convert_camel_case_to_lower_case_underscore(type_name) key = '%s/%s/%s' % (spec.base_type.pkg_name, subfolder, module_name) - includes[key] = '#include <%s__type_support.h>' % key + includes[key + '_support'] = '#include <%s__type_support.h>' % key + includes[key + '_struct'] = '#include <%s__struct.h>' % key + includes[key + '_functions'] = '#include <%s__functions.h>' % key for spec, subfolder in service_specs: type_name = convert_camel_case_to_lower_case_underscore(spec.srv_name) @@ -53,13 +61,27 @@ for spec, subfolder in service_specs: @[for spec, subfolder in message_specs]@ @{ +pkg_name = spec.base_type.pkg_name type_name = spec.base_type.type module_name = convert_camel_case_to_lower_case_underscore(type_name) +msg_typename = '%s__%s__%s' % (pkg_name, subfolder, type_name) }@ -void * @(spec.base_type.pkg_name)_@(module_name)__create_ros_message(void); -void @(spec.base_type.pkg_name)_@(module_name)__destroy_ros_message(void * raw_ros_message); -bool @(spec.base_type.pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); -PyObject * @(spec.base_type.pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message); + +static void * @(pkg_name)_@(module_name)__create_ros_message(void) +{ + return @(msg_typename)__create(); +} + +static void @(pkg_name)_@(module_name)__destroy_ros_message(void * raw_ros_message) +{ + @(msg_typename) * ros_message = (@(msg_typename) *)raw_ros_message; + @(msg_typename)__destroy(ros_message); +} + +IMPORT_API +bool @(pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); +IMPORT_API +PyObject * @(pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message); @[end for]@ static PyMethodDef @(package_name)__methods[] = { @@ -86,7 +108,7 @@ function_names = ['create_ros_message', 'destroy_ros_message', 'convert_from_py' ROSIDL_GENERATOR_C_IMPORT const rosidl_message_type_support_t * -ROSIDL_GET_MSG_TYPE_SUPPORT(@(spec.base_type.pkg_name), @(subfolder), @(spec.msg_name)); +ROSIDL_GET_MSG_TYPE_SUPPORT(@(pkg_name), @(subfolder), @(spec.msg_name)); int8_t _register_msg_type__@(type_name)(PyObject * pymodule) @@ -97,9 +119,9 @@ _register_msg_type__@(type_name)(PyObject * pymodule) PyObject * pyobject_@(function_name) = NULL; pyobject_@(function_name) = PyCapsule_New( @[ if function_name != 'type_support']@ - (void *)&@(spec.base_type.pkg_name)_@(type_name)__@(function_name), + (void *)&@(pkg_name)_@(type_name)__@(function_name), @[ else]@ - (void *)ROSIDL_GET_MSG_TYPE_SUPPORT(@(spec.base_type.pkg_name), @(subfolder), @(spec.msg_name)), + (void *)ROSIDL_GET_MSG_TYPE_SUPPORT(@(pkg_name), @(subfolder), @(spec.msg_name)), @[ end if]@ NULL, NULL); if (!pyobject_@(function_name)) { diff --git a/rosidl_generator_py/resource/_msg_support.c.em b/rosidl_generator_py/resource/_msg_support.c.em index cecf816c..096ddeaf 100644 --- a/rosidl_generator_py/resource/_msg_support.c.em +++ b/rosidl_generator_py/resource/_msg_support.c.em @@ -53,6 +53,28 @@ if not field.type.is_primitive_type() and field.type.is_array: msg_typename = '%s__%s__%s' % (spec.base_type.pkg_name, subfolder, spec.base_type.type) }@ +#ifdef WIN32 +# define EXPORT_API __declspec(dllexport) +# define IMPORT_API __declspec(dllimport) +#else +# define EXPORT_API __attribute__((visibility("default"))) +# define IMPORT_API +#endif + +@[for field in spec.fields]@ +@[ if not field.type.is_primitive_type()]@ +@[ if spec.base_type.pkg_name != field.type.pkg_name]@ +IMPORT_API +@[ end if]@ +bool @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(PyObject * _pymsg, void * _ros_message); +@[ if spec.base_type.pkg_name != field.type.pkg_name]@ +IMPORT_API +@[ end if]@ +PyObject * @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(void * raw_ros_message); +@[ end if]@ +@[end for]@ + +EXPORT_API bool @(spec.base_type.pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message) { @{ @@ -103,40 +125,6 @@ full_classname = '%s.%s._%s.%s' % (spec.base_type.pkg_name, subfolder, module_na @{ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) }@ - typedef bool (* convert_from_py_signature)(PyObject *, void *); - convert_from_py_signature convert_from_py = NULL; - // get conversion function - { - PyObject * msg_module = PyImport_ImportModule("@(field.type.pkg_name).msg._@convert_camel_case_to_lower_case_underscore(field.type.type)"); - if (!msg_module) { - Py_DECREF(field); - return false; - } - PyObject * msg_class = PyObject_GetAttrString(msg_module, "@(field.type.type)"); - Py_DECREF(msg_module); - if (!msg_class) { - Py_DECREF(field); - return false; - } - PyObject * msg_metaclass = PyObject_GetAttrString(msg_class, "__class__"); - Py_DECREF(msg_class); - if (!msg_metaclass) { - Py_DECREF(field); - return false; - } - PyObject * convert_from_py_ = PyObject_GetAttrString(msg_metaclass, "_CONVERT_FROM_PY"); - Py_DECREF(msg_metaclass); - if (!convert_from_py_) { - Py_DECREF(field); - return false; - } - convert_from_py = (convert_from_py_signature)PyCapsule_GetPointer(convert_from_py_, NULL); - Py_DECREF(convert_from_py_); - if (!convert_from_py) { - Py_DECREF(field); - return false; - } - } @[ if field.type.is_array]@ PyObject * seq_field = PySequence_Fast(field, "expected a sequence in '@(field.name)'"); if (!seq_field) { @@ -162,7 +150,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) @(nested_type) * dest = ros_message->@(field.name); @[ end if]@ for (Py_ssize_t i = 0; i < size; ++i) { - if (!convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { + if (!@(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { Py_DECREF(seq_field); Py_DECREF(field); return false; @@ -170,7 +158,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) } Py_DECREF(seq_field); @[ else]@ - if (!convert_from_py(field, &ros_message->@(field.name))) { + if (!@(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(field, &ros_message->@(field.name))) { Py_DECREF(field); return false; } @@ -317,17 +305,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) return true; } -void * @(spec.base_type.pkg_name)_@(module_name)__create_ros_message(void) -{ - return @(msg_typename)__create(); -} - -void @(spec.base_type.pkg_name)_@(module_name)__destroy_ros_message(void * raw_ros_message) -{ - @(msg_typename) * ros_message = (@(msg_typename) *)raw_ros_message; - @(msg_typename)__destroy(ros_message); -} - +EXPORT_API PyObject * @(spec.base_type.pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message) { /* NOTE(esteve): Call constructor of @(spec.base_type.type) */ @@ -355,35 +333,6 @@ PyObject * @(spec.base_type.pkg_name)_@(module_name)__convert_to_py(void * raw_r @{ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) }@ - typedef PyObject *(* convert_to_py_signature)(void *); - convert_to_py_signature convert_to_py = NULL; - // get conversion function - { - PyObject * msg_module = PyImport_ImportModule("@(field.type.pkg_name).msg._@convert_camel_case_to_lower_case_underscore(field.type.type)"); - if (!msg_module) { - return NULL; - } - PyObject * msg_class = PyObject_GetAttrString(msg_module, "@(field.type.type)"); - Py_DECREF(msg_module); - if (!msg_class) { - return NULL; - } - PyObject * msg_metaclass = PyObject_GetAttrString(msg_class, "__class__"); - Py_DECREF(msg_class); - if (!msg_metaclass) { - return NULL; - } - PyObject * convert_to_py_ = PyObject_GetAttrString(msg_metaclass, "_CONVERT_TO_PY"); - Py_DECREF(msg_metaclass); - if (!convert_to_py_) { - return NULL; - } - convert_to_py = (convert_to_py_signature)PyCapsule_GetPointer(convert_to_py_, NULL); - Py_DECREF(convert_to_py_); - if (!convert_to_py) { - return NULL; - } - } @[ if field.type.is_array]@ @[ if field.type.array_size is None or field.type.is_upper_bound]@ size_t size = ros_message->@(field.name).size; @@ -401,7 +350,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) @[ else]@ item = &(ros_message->@(field.name)[i]); @[ end if]@ - PyObject * pyitem = convert_to_py(item); + PyObject * pyitem = @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(item); if (!pyitem) { Py_DECREF(field); return NULL; @@ -412,7 +361,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) } assert(PySequence_Check(field)); @[ else]@ - field = convert_to_py(&ros_message->@(field.name)); + field = @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(&ros_message->@(field.name)); if (!field) { return NULL; } From d57d9389e7a8d8d4f14268ac51eaa4a2b0eaa6d5 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Fri, 24 Aug 2018 14:49:49 -0700 Subject: [PATCH 02/12] generate single _python lib per package --- ...idl_generator_py_generate_interfaces.cmake | 91 +++++++++++-------- 1 file changed, 51 insertions(+), 40 deletions(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index 93f83a7d..d7ae057f 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -199,31 +199,45 @@ macro(set_lib_properties _build_type) RUNTIME_OUTPUT_DIRECTORY${_build_type} ${_output_path}) endmacro() +set(_target_name_lib "${rosidl_generate_interfaces_TARGET}__python") +add_library(${_target_name_lib} SHARED + ${_generated_msg_c_files} + ${_generated_srv_c_files} +) +add_dependencies( + ${_target_name_lib} + ${rosidl_generate_interfaces_TARGET}${_target_suffix} + ${rosidl_generate_interfaces_TARGET}__rosidl_typesupport_c +) + +target_link_libraries( + ${_target_name_lib} + ${PythonExtra_LIBRARIES} +) +target_include_directories(${_target_name_lib} + PUBLIC + ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c + ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_py + ${PythonExtra_INCLUDE_DIRS} +) + +rosidl_target_interfaces(${_target_name_lib} + ${rosidl_generate_interfaces_TARGET} rosidl_typesupport_c) + foreach(_typesupport_impl ${_typesupport_impls}) find_package(${_typesupport_impl} REQUIRED) set(_pyext_suffix "__pyext") set(_target_name "${PROJECT_NAME}__${_typesupport_impl}${_pyext_suffix}") - set(_target_name_lib "${PROJECT_NAME}__python_${_typesupport_impl}") add_library(${_target_name} SHARED ${_generated_extension_${_typesupport_impl}_files} ) - add_library(${_target_name_lib} SHARED - ${_generated_msg_c_files} - ${_generated_srv_c_files} - ) - add_dependencies( ${_target_name} ${rosidl_generate_interfaces_TARGET}${_target_suffix} ${rosidl_generate_interfaces_TARGET}__rosidl_typesupport_c ) - add_dependencies( - ${_target_name_lib} - ${rosidl_generate_interfaces_TARGET}${_target_suffix} - ${rosidl_generate_interfaces_TARGET}__rosidl_typesupport_c - ) set(_extension_compile_flags "") set(_PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE}) @@ -239,10 +253,6 @@ foreach(_typesupport_impl ${_typesupport_impls}) ${PythonExtra_LIBRARIES} ${rosidl_generate_interfaces_TARGET}__${_typesupport_impl} ) - target_link_libraries( - ${_target_name_lib} - ${PythonExtra_LIBRARIES} - ) target_include_directories(${_target_name} PUBLIC @@ -250,14 +260,8 @@ foreach(_typesupport_impl ${_typesupport_impls}) ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_py ${PythonExtra_INCLUDE_DIRS} ) - target_include_directories(${_target_name_lib} - PUBLIC - ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_c - ${CMAKE_CURRENT_BINARY_DIR}/rosidl_generator_py - ${PythonExtra_INCLUDE_DIRS} - ) - rosidl_target_interfaces(${_target_name_lib} + rosidl_target_interfaces(${_target_name} ${rosidl_generate_interfaces_TARGET} rosidl_typesupport_c) ament_target_dependencies(${_target_name} @@ -270,28 +274,14 @@ foreach(_typesupport_impl ${_typesupport_impls}) ${_pkg_name} ) - set(_pkg_base "${${_pkg_name}_DIR}/../../..") - set(_pkg_filename "${_pkg_name}__python_${_typesupport_impl}") - - if(WIN32) - target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/${_pkg_filename}.lib") - else() - target_link_libraries(${_target_name_lib} "${_pkg_base}/lib/lib${_pkg_filename}.so") - endif() - endforeach() set_properties("") - set_lib_properties("") if(WIN32) set_properties("_DEBUG") set_properties("_MINSIZEREL") set_properties("_RELEASE") set_properties("_RELWITHDEBINFO") - set_lib_properties("_DEBUG") - set_lib_properties("_MINSIZEREL") - set_lib_properties("_RELEASE") - set_lib_properties("_RELWITHDEBINFO") endif() add_dependencies(${_target_name} @@ -307,13 +297,34 @@ foreach(_typesupport_impl ${_typesupport_impls}) if(NOT rosidl_generate_interfaces_SKIP_INSTALL) install(TARGETS ${_target_name} DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}") - install(TARGETS ${_target_name_lib} - ARCHIVE DESTINATION lib - LIBRARY DESTINATION lib - RUNTIME DESTINATION bin) endif() endforeach() +foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) + set(_pkg_base "${${_pkg_name}_DIR}/../../..") + set(_pkg_filename "${_pkg_name}__python") + + if(WIN32) + target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/${_pkg_filename}.lib") + else() + target_link_libraries(${_target_name_lib} "${_pkg_base}/lib/lib${_pkg_filename}.so") + endif() +endforeach() + +set_lib_properties("") +if(WIN32) + set_lib_properties("_DEBUG") + set_lib_properties("_MINSIZEREL") + set_lib_properties("_RELEASE") + set_lib_properties("_RELWITHDEBINFO") +endif() +if(NOT rosidl_generate_interfaces_SKIP_INSTALL) + install(TARGETS ${_target_name_lib} + ARCHIVE DESTINATION lib + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin) +endif() + if(BUILD_TESTING AND rosidl_generate_interfaces_ADD_LINTER_TESTS) if( NOT _generated_msg_py_files STREQUAL "" OR From 6125bc9030d7105ad5f9a7fef036e7548c452035 Mon Sep 17 00:00:00 2001 From: Martins Mozeiko Date: Thu, 6 Sep 2018 10:46:41 -0700 Subject: [PATCH 03/12] use visibility macros from visibility_control.h --- .../_msg_pkg_typesupport_entry_point.c.em | 10 +++------- rosidl_generator_py/resource/_msg_support.c.em | 17 +++++------------ 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em index d5ed28b3..5ecbbdac 100644 --- a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em +++ b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em @@ -18,11 +18,7 @@ #include #include -#ifdef WIN32 -# define IMPORT_API __declspec(dllimport) -#else -# define IMPORT_API -#endif +#include @{ static_includes = set([ @@ -78,9 +74,9 @@ static void @(pkg_name)_@(module_name)__destroy_ros_message(void * raw_ros_messa @(msg_typename)__destroy(ros_message); } -IMPORT_API +ROSIDL_GENERATOR_C_IMPORT bool @(pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); -IMPORT_API +ROSIDL_GENERATOR_C_IMPORT PyObject * @(pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message); @[end for]@ diff --git a/rosidl_generator_py/resource/_msg_support.c.em b/rosidl_generator_py/resource/_msg_support.c.em index 096ddeaf..b9d8bcf1 100644 --- a/rosidl_generator_py/resource/_msg_support.c.em +++ b/rosidl_generator_py/resource/_msg_support.c.em @@ -15,6 +15,7 @@ #include #include +#include #include <@(spec.base_type.pkg_name)/@(subfolder)/@(module_name)__struct.h> #include <@(spec.base_type.pkg_name)/@(subfolder)/@(module_name)__functions.h> @@ -53,28 +54,20 @@ if not field.type.is_primitive_type() and field.type.is_array: msg_typename = '%s__%s__%s' % (spec.base_type.pkg_name, subfolder, spec.base_type.type) }@ -#ifdef WIN32 -# define EXPORT_API __declspec(dllexport) -# define IMPORT_API __declspec(dllimport) -#else -# define EXPORT_API __attribute__((visibility("default"))) -# define IMPORT_API -#endif - @[for field in spec.fields]@ @[ if not field.type.is_primitive_type()]@ @[ if spec.base_type.pkg_name != field.type.pkg_name]@ -IMPORT_API +ROSIDL_GENERATOR_C_IMPORT @[ end if]@ bool @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(PyObject * _pymsg, void * _ros_message); @[ if spec.base_type.pkg_name != field.type.pkg_name]@ -IMPORT_API +ROSIDL_GENERATOR_C_IMPORT @[ end if]@ PyObject * @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(void * raw_ros_message); @[ end if]@ @[end for]@ -EXPORT_API +ROSIDL_GENERATOR_C_EXPORT bool @(spec.base_type.pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message) { @{ @@ -305,7 +298,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) return true; } -EXPORT_API +ROSIDL_GENERATOR_C_EXPORT PyObject * @(spec.base_type.pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message) { /* NOTE(esteve): Call constructor of @(spec.base_type.type) */ From 7d8629c87c1fc9b184ca152ad0bb45b88df02abe Mon Sep 17 00:00:00 2001 From: Martins Mozeiko Date: Thu, 6 Sep 2018 10:55:18 -0700 Subject: [PATCH 04/12] use dylib extension for libraries on macOS --- .../cmake/rosidl_generator_py_generate_interfaces.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index d7ae057f..0a2f254c 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -306,6 +306,8 @@ foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) if(WIN32) target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/${_pkg_filename}.lib") + elseif(APPLE) + target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/lib${_pkg_filename}.dylib") else() target_link_libraries(${_target_name_lib} "${_pkg_base}/lib/lib${_pkg_filename}.so") endif() From 77009ae53162e2c1ae6c53bae307cff417820351 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Mon, 10 Sep 2018 10:46:03 -0700 Subject: [PATCH 05/12] spurious line change --- .../cmake/rosidl_generator_py_generate_interfaces.cmake | 1 - 1 file changed, 1 deletion(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index 0a2f254c..bece136e 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -273,7 +273,6 @@ foreach(_typesupport_impl ${_typesupport_impls}) ament_target_dependencies(${_target_name} ${_pkg_name} ) - endforeach() set_properties("") From 617e0c67c0a26509e6c0a110aed16bb2d2aa1f76 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Mon, 10 Sep 2018 10:46:17 -0700 Subject: [PATCH 06/12] remove duplicated include --- .../resource/_msg_pkg_typesupport_entry_point.c.em | 2 -- 1 file changed, 2 deletions(-) diff --git a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em index 5ecbbdac..ec480334 100644 --- a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em +++ b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em @@ -18,8 +18,6 @@ #include #include -#include - @{ static_includes = set([ '#include ', From f931dbd5662fc7c3385aa97f93143fa247576148 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Mon, 10 Sep 2018 10:46:41 -0700 Subject: [PATCH 07/12] blank line fixups --- rosidl_generator_py/resource/_msg_support.c.em | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rosidl_generator_py/resource/_msg_support.c.em b/rosidl_generator_py/resource/_msg_support.c.em index b9d8bcf1..df0cadb2 100644 --- a/rosidl_generator_py/resource/_msg_support.c.em +++ b/rosidl_generator_py/resource/_msg_support.c.em @@ -16,6 +16,7 @@ #include #include + #include <@(spec.base_type.pkg_name)/@(subfolder)/@(module_name)__struct.h> #include <@(spec.base_type.pkg_name)/@(subfolder)/@(module_name)__functions.h> @@ -53,7 +54,7 @@ if not field.type.is_primitive_type() and field.type.is_array: @{ msg_typename = '%s__%s__%s' % (spec.base_type.pkg_name, subfolder, spec.base_type.type) }@ - +@ @[for field in spec.fields]@ @[ if not field.type.is_primitive_type()]@ @[ if spec.base_type.pkg_name != field.type.pkg_name]@ From 5768b2ee1533b982f5da8f08a351573cb6947e35 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 11 Sep 2018 09:06:58 -0700 Subject: [PATCH 08/12] revert unnecessary code relocation --- .../rosidl_generator_py_generate_interfaces.cmake | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index bece136e..c8d5e19e 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -247,6 +247,13 @@ foreach(_typesupport_impl ${_typesupport_impls}) if(WIN32 AND "${CMAKE_BUILD_TYPE}" STREQUAL "Debug") set(PYTHON_EXECUTABLE ${PYTHON_EXECUTABLE_DEBUG}) endif() + set_properties("") + if(WIN32) + set_properties("_DEBUG") + set_properties("_MINSIZEREL") + set_properties("_RELEASE") + set_properties("_RELWITHDEBINFO") + endif() target_link_libraries( ${_target_name} ${_target_name_lib} @@ -275,14 +282,6 @@ foreach(_typesupport_impl ${_typesupport_impls}) ) endforeach() - set_properties("") - if(WIN32) - set_properties("_DEBUG") - set_properties("_MINSIZEREL") - set_properties("_RELEASE") - set_properties("_RELWITHDEBINFO") - endif() - add_dependencies(${_target_name} ${rosidl_generate_interfaces_TARGET}__${_typesupport_impl} ) From c58d5daeb4970f40898bc1cf97c033a473c34d84 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 11 Sep 2018 09:07:50 -0700 Subject: [PATCH 09/12] rename variables and use lib folder instad of Lib on macos --- .../rosidl_generator_py_generate_interfaces.cmake | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index c8d5e19e..4d869a98 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -299,15 +299,17 @@ foreach(_typesupport_impl ${_typesupport_impls}) endforeach() foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) - set(_pkg_base "${${_pkg_name}_DIR}/../../..") - set(_pkg_filename "${_pkg_name}__python") + set(_pkg_install_base "${${_pkg_name}_DIR}/../../..") + set(_pkg_python_libname "${_pkg_name}__python") + message(WARNING "${${_pkg_name}_ROOT}") + message(WARNING "${${_pkg_name}_DIR}") if(WIN32) - target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/${_pkg_filename}.lib") + target_link_libraries(${_target_name_lib} "${_pkg_install_base}/Lib/${_pkg_python_libname}.lib") elseif(APPLE) - target_link_libraries(${_target_name_lib} "${_pkg_base}/Lib/lib${_pkg_filename}.dylib") + target_link_libraries(${_target_name_lib} "${_pkg_install_base}/lib/lib${_pkg_python_libname}.dylib") else() - target_link_libraries(${_target_name_lib} "${_pkg_base}/lib/lib${_pkg_filename}.so") + target_link_libraries(${_target_name_lib} "${_pkg_install_base}/lib/lib${_pkg_python_libname}.so") endif() endforeach() From 36010bcf4653d75d586721cd6049e652ba49b385 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 11 Sep 2018 09:13:41 -0700 Subject: [PATCH 10/12] create lowercase_field_type for readability and reuse --- rosidl_generator_py/resource/_msg_support.c.em | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/rosidl_generator_py/resource/_msg_support.c.em b/rosidl_generator_py/resource/_msg_support.c.em index df0cadb2..28807803 100644 --- a/rosidl_generator_py/resource/_msg_support.c.em +++ b/rosidl_generator_py/resource/_msg_support.c.em @@ -56,15 +56,16 @@ msg_typename = '%s__%s__%s' % (spec.base_type.pkg_name, subfolder, spec.base_typ }@ @ @[for field in spec.fields]@ +@{lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.type)}@ @[ if not field.type.is_primitive_type()]@ @[ if spec.base_type.pkg_name != field.type.pkg_name]@ ROSIDL_GENERATOR_C_IMPORT @[ end if]@ -bool @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(PyObject * _pymsg, void * _ros_message); +bool @(field.type.pkg_name)_@(lowercase_field_type)__convert_from_py(PyObject * _pymsg, void * _ros_message); @[ if spec.base_type.pkg_name != field.type.pkg_name]@ ROSIDL_GENERATOR_C_IMPORT @[ end if]@ -PyObject * @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(void * raw_ros_message); +PyObject * @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(void * raw_ros_message); @[ end if]@ @[end for]@ @@ -118,6 +119,7 @@ full_classname = '%s.%s._%s.%s' % (spec.base_type.pkg_name, subfolder, module_na @[ if not field.type.is_primitive_type()]@ @{ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) +lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.type) }@ @[ if field.type.is_array]@ PyObject * seq_field = PySequence_Fast(field, "expected a sequence in '@(field.name)'"); @@ -144,7 +146,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) @(nested_type) * dest = ros_message->@(field.name); @[ end if]@ for (Py_ssize_t i = 0; i < size; ++i) { - if (!@(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { + if (!@(field.type.pkg_name)_@(lowercase_field_type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { Py_DECREF(seq_field); Py_DECREF(field); return false; @@ -152,7 +154,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) } Py_DECREF(seq_field); @[ else]@ - if (!@(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_from_py(field, &ros_message->@(field.name))) { + if (!@(field.type.pkg_name)_@(lowercase_field_type)__convert_from_py(field, &ros_message->@(field.name))) { Py_DECREF(field); return false; } @@ -326,6 +328,7 @@ PyObject * @(spec.base_type.pkg_name)_@(module_name)__convert_to_py(void * raw_r @[ if not field.type.is_primitive_type()]@ @{ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) +lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.type) }@ @[ if field.type.is_array]@ @[ if field.type.array_size is None or field.type.is_upper_bound]@ @@ -344,7 +347,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) @[ else]@ item = &(ros_message->@(field.name)[i]); @[ end if]@ - PyObject * pyitem = @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(item); + PyObject * pyitem = @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(item); if (!pyitem) { Py_DECREF(field); return NULL; @@ -355,7 +358,7 @@ nested_type = '%s__%s__%s' % (field.type.pkg_name, 'msg', field.type.type) } assert(PySequence_Check(field)); @[ else]@ - field = @(field.type.pkg_name)_@convert_camel_case_to_lower_case_underscore(field.type.type)__convert_to_py(&ros_message->@(field.name)); + field = @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(&ros_message->@(field.name)); if (!field) { return NULL; } From f8b7dbc7f3d7369bd5f3c77c76e51f740ddbc124 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Tue, 11 Sep 2018 09:22:55 -0700 Subject: [PATCH 11/12] remove debug prints --- .../cmake/rosidl_generator_py_generate_interfaces.cmake | 2 -- 1 file changed, 2 deletions(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index 4d869a98..e10a5558 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -301,8 +301,6 @@ endforeach() foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES}) set(_pkg_install_base "${${_pkg_name}_DIR}/../../..") set(_pkg_python_libname "${_pkg_name}__python") - message(WARNING "${${_pkg_name}_ROOT}") - message(WARNING "${${_pkg_name}_DIR}") if(WIN32) target_link_libraries(${_target_name_lib} "${_pkg_install_base}/Lib/${_pkg_python_libname}.lib") From 18d2af12adc34c322bf2e8ec8d49e66e62460e19 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Wed, 12 Sep 2018 17:17:40 -0700 Subject: [PATCH 12/12] rename functions to use double underscore between package name and field type --- .../_msg_pkg_typesupport_entry_point.c.em | 10 +++++----- rosidl_generator_py/resource/_msg_support.c.em | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em index ec480334..21d12c48 100644 --- a/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em +++ b/rosidl_generator_py/resource/_msg_pkg_typesupport_entry_point.c.em @@ -61,21 +61,21 @@ module_name = convert_camel_case_to_lower_case_underscore(type_name) msg_typename = '%s__%s__%s' % (pkg_name, subfolder, type_name) }@ -static void * @(pkg_name)_@(module_name)__create_ros_message(void) +static void * @(pkg_name)__@(module_name)__create_ros_message(void) { return @(msg_typename)__create(); } -static void @(pkg_name)_@(module_name)__destroy_ros_message(void * raw_ros_message) +static void @(pkg_name)__@(module_name)__destroy_ros_message(void * raw_ros_message) { @(msg_typename) * ros_message = (@(msg_typename) *)raw_ros_message; @(msg_typename)__destroy(ros_message); } ROSIDL_GENERATOR_C_IMPORT -bool @(pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); +bool @(pkg_name)__@(module_name)__convert_from_py(PyObject * _pymsg, void * ros_message); ROSIDL_GENERATOR_C_IMPORT -PyObject * @(pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message); +PyObject * @(pkg_name)__@(module_name)__convert_to_py(void * raw_ros_message); @[end for]@ static PyMethodDef @(package_name)__methods[] = { @@ -113,7 +113,7 @@ _register_msg_type__@(type_name)(PyObject * pymodule) PyObject * pyobject_@(function_name) = NULL; pyobject_@(function_name) = PyCapsule_New( @[ if function_name != 'type_support']@ - (void *)&@(pkg_name)_@(type_name)__@(function_name), + (void *)&@(pkg_name)__@(type_name)__@(function_name), @[ else]@ (void *)ROSIDL_GET_MSG_TYPE_SUPPORT(@(pkg_name), @(subfolder), @(spec.msg_name)), @[ end if]@ diff --git a/rosidl_generator_py/resource/_msg_support.c.em b/rosidl_generator_py/resource/_msg_support.c.em index 28807803..7d297951 100644 --- a/rosidl_generator_py/resource/_msg_support.c.em +++ b/rosidl_generator_py/resource/_msg_support.c.em @@ -61,16 +61,16 @@ msg_typename = '%s__%s__%s' % (spec.base_type.pkg_name, subfolder, spec.base_typ @[ if spec.base_type.pkg_name != field.type.pkg_name]@ ROSIDL_GENERATOR_C_IMPORT @[ end if]@ -bool @(field.type.pkg_name)_@(lowercase_field_type)__convert_from_py(PyObject * _pymsg, void * _ros_message); +bool @(field.type.pkg_name)__@(lowercase_field_type)__convert_from_py(PyObject * _pymsg, void * _ros_message); @[ if spec.base_type.pkg_name != field.type.pkg_name]@ ROSIDL_GENERATOR_C_IMPORT @[ end if]@ -PyObject * @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(void * raw_ros_message); +PyObject * @(field.type.pkg_name)__@(lowercase_field_type)__convert_to_py(void * raw_ros_message); @[ end if]@ @[end for]@ ROSIDL_GENERATOR_C_EXPORT -bool @(spec.base_type.pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message) +bool @(spec.base_type.pkg_name)__@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message) { @{ full_classname = '%s.%s._%s.%s' % (spec.base_type.pkg_name, subfolder, module_name, spec.base_type.type) @@ -146,7 +146,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty @(nested_type) * dest = ros_message->@(field.name); @[ end if]@ for (Py_ssize_t i = 0; i < size; ++i) { - if (!@(field.type.pkg_name)_@(lowercase_field_type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { + if (!@(field.type.pkg_name)__@(lowercase_field_type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) { Py_DECREF(seq_field); Py_DECREF(field); return false; @@ -154,7 +154,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty } Py_DECREF(seq_field); @[ else]@ - if (!@(field.type.pkg_name)_@(lowercase_field_type)__convert_from_py(field, &ros_message->@(field.name))) { + if (!@(field.type.pkg_name)__@(lowercase_field_type)__convert_from_py(field, &ros_message->@(field.name))) { Py_DECREF(field); return false; } @@ -302,7 +302,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty } ROSIDL_GENERATOR_C_EXPORT -PyObject * @(spec.base_type.pkg_name)_@(module_name)__convert_to_py(void * raw_ros_message) +PyObject * @(spec.base_type.pkg_name)__@(module_name)__convert_to_py(void * raw_ros_message) { /* NOTE(esteve): Call constructor of @(spec.base_type.type) */ PyObject * _pymessage = NULL; @@ -347,7 +347,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty @[ else]@ item = &(ros_message->@(field.name)[i]); @[ end if]@ - PyObject * pyitem = @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(item); + PyObject * pyitem = @(field.type.pkg_name)__@(lowercase_field_type)__convert_to_py(item); if (!pyitem) { Py_DECREF(field); return NULL; @@ -358,7 +358,7 @@ lowercase_field_type = convert_camel_case_to_lower_case_underscore(field.type.ty } assert(PySequence_Check(field)); @[ else]@ - field = @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(&ros_message->@(field.name)); + field = @(field.type.pkg_name)__@(lowercase_field_type)__convert_to_py(&ros_message->@(field.name)); if (!field) { return NULL; }