Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Call conversion functions directly #10

Merged
merged 12 commits into from
Sep 18, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,38 @@ 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()

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)

Expand All @@ -200,10 +232,7 @@ foreach(_typesupport_impl ${_typesupport_impls})

add_library(${_target_name} SHARED
${_generated_extension_${_typesupport_impl}_files}
${_generated_msg_c_files}
${_generated_srv_c_files}
)

add_dependencies(
${_target_name}
${rosidl_generate_interfaces_TARGET}${_target_suffix}
Expand All @@ -227,6 +256,7 @@ foreach(_typesupport_impl ${_typesupport_impls})
endif()
target_link_libraries(
${_target_name}
${_target_name_lib}
${PythonExtra_LIBRARIES}
${rosidl_generate_interfaces_TARGET}__${_typesupport_impl}
)
Expand Down Expand Up @@ -268,6 +298,33 @@ foreach(_typesupport_impl ${_typesupport_impls})
endif()
endforeach()

foreach(_pkg_name ${rosidl_generate_interfaces_DEPENDENCY_PACKAGE_NAMES})
set(_pkg_install_base "${${_pkg_name}_DIR}/../../..")
set(_pkg_python_libname "${_pkg_name}__python")

if(WIN32)
target_link_libraries(${_target_name_lib} "${_pkg_install_base}/Lib/${_pkg_python_libname}.lib")
elseif(APPLE)
target_link_libraries(${_target_name_lib} "${_pkg_install_base}/lib/lib${_pkg_python_libname}.dylib")
else()
target_link_libraries(${_target_name_lib} "${_pkg_install_base}/lib/lib${_pkg_python_libname}.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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,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)
Expand All @@ -53,13 +55,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);
}

ROSIDL_GENERATOR_C_IMPORT
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);
@[end for]@

static PyMethodDef @(package_name)__methods[] = {
Expand All @@ -86,7 +102,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)
Expand All @@ -97,9 +113,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)) {
Expand Down
102 changes: 24 additions & 78 deletions rosidl_generator_py/resource/_msg_support.c.em
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include <Python.h>
#include <stdbool.h>

#include <rosidl_generator_c/visibility_control.h>

#include <@(spec.base_type.pkg_name)/@(subfolder)/@(module_name)__struct.h>
#include <@(spec.base_type.pkg_name)/@(subfolder)/@(module_name)__functions.h>

Expand Down Expand Up @@ -52,7 +54,22 @@ 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]@
@{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)_@(lowercase_field_type)__convert_from_py(PyObject * _pymsg, void * _ros_message);
mikaelarguedas marked this conversation as resolved.
Show resolved Hide resolved
@[ 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);
@[ end if]@
@[end for]@

ROSIDL_GENERATOR_C_EXPORT
bool @(spec.base_type.pkg_name)_@(module_name)__convert_from_py(PyObject * _pymsg, void * _ros_message)
{
@{
Expand Down Expand Up @@ -102,41 +119,8 @@ 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)
}@
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) {
Expand All @@ -162,15 +146,15 @@ 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)_@(lowercase_field_type)__convert_from_py(PySequence_Fast_GET_ITEM(seq_field, i), &dest[i])) {
Py_DECREF(seq_field);
Py_DECREF(field);
return false;
}
}
Py_DECREF(seq_field);
@[ else]@
if (!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;
}
Expand Down Expand Up @@ -317,17 +301,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);
}

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) */
Expand All @@ -354,36 +328,8 @@ 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)
}@
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;
Expand All @@ -401,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 = convert_to_py(item);
PyObject * pyitem = @(field.type.pkg_name)_@(lowercase_field_type)__convert_to_py(item);
if (!pyitem) {
Py_DECREF(field);
return NULL;
Expand All @@ -412,7 +358,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)_@(lowercase_field_type)__convert_to_py(&ros_message->@(field.name));
if (!field) {
return NULL;
}
Expand Down