Skip to content

Commit

Permalink
actions: initial action idl generation
Browse files Browse the repository at this point in the history
  • Loading branch information
hoffmann-stefan committed Jun 22, 2022
1 parent 664ee0b commit adebb26
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 7 deletions.
1 change: 1 addition & 0 deletions rcldotnet_common/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ find_package(DotNETExtra REQUIRED)

set(CS_SOURCES
DllLoadUtils.cs
IRosActionDefinition.cs
IRosMessage.cs
IRosServiceDefinition.cs
)
Expand Down
27 changes: 27 additions & 0 deletions rcldotnet_common/IRosActionDefinition.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* Copyright 2022 Stefan Hoffmann <stefan.hoffmann@schiller.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

namespace ROS2
{
public interface IRosActionDefinition<TGoal, TResult, TFeedback>
where TGoal : IRosMessage, new()
where TResult : IRosMessage, new()
where TFeedback : IRosMessage, new()
{
// must be implemented on deriving types, gets called via reflection
// (static abstract interface members are not supported yet.)
// public static abstract IntPtr __GetTypeSupport();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,17 @@ foreach(_abs_idl_file ${rosidl_generate_interfaces_ABS_IDL_FILES})
"${_output_path}/${_parent_folder}/${_module_name}.c"
)
elseif(_parent_folder STREQUAL "action")
list(APPEND _generated_cs_files
"${_output_path}/${_parent_folder}/${_module_name}.cs"
)

list(APPEND _generated_h_files
"${_output_path}/${_parent_folder}/rcldotnet_${_module_name}.h"
)

list(APPEND _generated_c_ts_files
"${_output_path}/${_parent_folder}/${_module_name}.c"
)
else()
message(FATAL_ERROR "Interface file with unknown parent folder: ${_idl_file}")
endif()
Expand All @@ -87,13 +98,18 @@ endforeach()
set(target_dependencies
"${rosidl_generator_dotnet_BIN}"
${rosidl_generator_dotnet_GENERATOR_FILES}
"${rosidl_generator_dotnet_TEMPLATE_DIR}/idl.h.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/action.c.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/action.cs.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/action.h.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/idl.c.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/idl.cs.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/msg.h.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/idl.h.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/msg.c.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/msg.cs.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/msg.h.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/srv.c.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/srv.cs.em"
"${rosidl_generator_dotnet_TEMPLATE_DIR}/srv.h.em"
${rosidl_generate_interfaces_ABS_IDL_FILES}
${_dependency_files})
foreach(dep ${target_dependencies})
Expand Down
8 changes: 8 additions & 0 deletions rosidl_generator_dotnet/resource/action.c.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@{
type_name = action.namespaced_type.name
action_typename = '%s__%s' % ('__'.join(action.namespaced_type.namespaces), type_name)
}@
const void * @(action_typename)__get_typesupport(void) {
const void * ptr = ROSIDL_TYPESUPPORT_INTERFACE__ACTION_SYMBOL_NAME(rosidl_typesupport_c, @(', '.join(action.namespaced_type.namespaced_name())))();
return ptr;
}
61 changes: 61 additions & 0 deletions rosidl_generator_dotnet/resource/action.cs.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@{
from rosidl_generator_dotnet import get_field_name
from rosidl_generator_dotnet import get_dotnet_type
from rosidl_generator_dotnet import get_builtin_dotnet_type
from rosidl_generator_dotnet import constant_value_to_dotnet

from rosidl_parser.definition import AbstractNestedType
from rosidl_parser.definition import AbstractGenericString
from rosidl_parser.definition import AbstractString
from rosidl_parser.definition import AbstractWString
from rosidl_parser.definition import AbstractSequence
from rosidl_parser.definition import Array
from rosidl_parser.definition import BasicType
from rosidl_parser.definition import NamespacedType

type_name = action.namespaced_type.name
goal_type_name = action.goal.structure.namespaced_type.name
result_type_name = action.result.structure.namespaced_type.name
feedback_type_name = action.feedback.structure.namespaced_type.name
action_typename = '%s__%s' % ('__'.join(action.namespaced_type.namespaces), type_name)
}
namespace @('.'.join(action.namespaced_type.namespaces))
{
@# sealed class with private constructor -> no instance can be created
@# static classes can't implement an interface (or any other basetype),
@# but we need some type that can hold the typesupport and be passed to the Node.CreateActionServce/Client() method.
@# So sealed + private constructor is as static as it gets.
@# static abstract interface members are currently in preview, so maybe we could use the feature in the future.
@# (if hey add support to derive from static only interfaces in static classes)
@# Another option is to not use generics for passing the typesupport, but lets try this until we hit some wall.
public sealed class @(type_name) : global::ROS2.IRosActionDefinition<@(goal_type_name), @(result_type_name), @(feedback_type_name)>
{
private static readonly DllLoadUtils dllLoadUtils;

private @(type_name)()
{
}

static @(type_name)()
{
dllLoadUtils = DllLoadUtilsFactory.GetDllLoadUtils();
IntPtr nativelibrary = dllLoadUtils.LoadLibrary("@(package_name)__dotnetext");

IntPtr native_get_typesupport_ptr = dllLoadUtils.GetProcAddress(nativelibrary, "@(action_typename)__get_typesupport");

@(type_name).native_get_typesupport = (NativeGetTypeSupportType)Marshal.GetDelegateForFunctionPointer(
native_get_typesupport_ptr, typeof(NativeGetTypeSupportType));
}

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate IntPtr NativeGetTypeSupportType();

private static NativeGetTypeSupportType native_get_typesupport = null;

@# This method gets called via reflection as static abstract interface members are not supported yet.
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
public static IntPtr __GetTypeSupport() {
return native_get_typesupport();
}
}
}
33 changes: 33 additions & 0 deletions rosidl_generator_dotnet/resource/action.h.em
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@{
type_name = action.namespaced_type.name
action_typename = '%s__%s' % ('__'.join(action.namespaced_type.namespaces), type_name)
action_prefix = "RCLDOTNET_{0}_{1}_{2}".format(package_name, '_'.join(action.namespaced_type.namespaces), type_name).upper()
}@
#if defined(_MSC_VER)
// Microsoft
#define @(action_prefix)_EXPORT __declspec(dllexport)
#define @(action_prefix)_IMPORT __declspec(dllimport)
#if defined(_M_IX86)
#define @(action_prefix)_CDECL __cdecl
#else
#define @(action_prefix)_CDECL
#endif
#elif defined(__GNUC__)
// GCC
#define @(action_prefix)_EXPORT __attribute__((visibility("default")))
#define @(action_prefix)_IMPORT
#if defined(__i386__)
#define @(action_prefix)_CDECL __attribute__((__cdecl__))
#else
#define @(action_prefix)_CDECL
#endif
#else
// do nothing and hope for the best?
#define @(action_prefix)_EXPORT
#define @(action_prefix)_IMPORT
#define @(action_prefix)_CDECL
#pragma warning Unknown dynamic link import/export semantics.
#endif

@(action_prefix)_EXPORT
const void * @(action_prefix)_CDECL @(action_typename)__get_typesupport(void);
73 changes: 71 additions & 2 deletions rosidl_generator_dotnet/resource/idl.c.em
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,74 @@ TEMPLATE(
@# Handle actions
@#######################################################################
@
@#TODO - actions not implemented
@
@{
from rosidl_parser.definition import Action
}@
@[for action in content.get_elements_of_type(Action)]@
@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.goal)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.result)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.feedback)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.send_goal_service.request_message)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.send_goal_service.response_message)
}@

@{
TEMPLATE(
'srv.c.em',
package_name=package_name, interface_path=interface_path, service=action.send_goal_service)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.get_result_service.request_message)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.get_result_service.response_message)
}@

@{
TEMPLATE(
'srv.c.em',
package_name=package_name, interface_path=interface_path, service=action.get_result_service)
}@

@{
TEMPLATE(
'msg.c.em',
package_name=package_name, interface_path=interface_path, message=action.feedback_message)
}@

@{
TEMPLATE(
'action.c.em',
package_name=package_name, interface_path=interface_path, action=action)
}@
@[end for]@
@
73 changes: 71 additions & 2 deletions rosidl_generator_dotnet/resource/idl.cs.em
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,74 @@ TEMPLATE(
@# Handle actions
@#######################################################################
@
@#TODO - actions not implemented
@
@{
from rosidl_parser.definition import Action
}@
@[for action in content.get_elements_of_type(Action)]@
@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.goal)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.result)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.feedback)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.send_goal_service.request_message)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.send_goal_service.response_message)
}@

@{
TEMPLATE(
'srv.cs.em',
package_name=package_name, interface_path=interface_path, service=action.send_goal_service)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.get_result_service.request_message)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.get_result_service.response_message)
}@

@{
TEMPLATE(
'srv.cs.em',
package_name=package_name, interface_path=interface_path, service=action.get_result_service)
}@

@{
TEMPLATE(
'msg.cs.em',
package_name=package_name, interface_path=interface_path, message=action.feedback_message)
}@

@{
TEMPLATE(
'action.cs.em',
package_name=package_name, interface_path=interface_path, action=action)
}@
@[end for]@
@
Loading

0 comments on commit adebb26

Please sign in to comment.