@@ -136,6 +136,29 @@ get_library()
136136 return g_rmw_lib;
137137}
138138
139+ std::shared_ptr<rcpputils::SharedLibrary>
140+ get_wrap_library ()
141+ {
142+ static bool tried_load = false ;
143+ static std::shared_ptr<rcpputils::SharedLibrary> wrap_lib = nullptr ;
144+ if (!wrap_lib && !tried_load) {
145+ tried_load = true ;
146+ std::string wrapper_var;
147+ try {
148+ wrapper_var = rcpputils::get_env_var (" RMW_IMPLEMENTATION_WRAPPER" );
149+ } catch (const std::exception & e) {
150+ RMW_SET_ERROR_MSG_WITH_FORMAT_STRING (
151+ " failed to fetch RMW_IMPLEMENTATION_WRAPPER "
152+ " from environment due to %s" , e.what ());
153+ return nullptr ;
154+ }
155+ if (!wrapper_var.empty ()) {
156+ wrap_lib = attempt_to_load_one_rmw (wrapper_var);
157+ }
158+ }
159+ return wrap_lib;
160+ }
161+
139162void *
140163lookup_symbol (std::shared_ptr<rcpputils::SharedLibrary> lib, const std::string & symbol_name)
141164{
@@ -175,6 +198,25 @@ get_symbol(const char * symbol_name)
175198 }
176199}
177200
201+ void * get_wrap_symbol (const char * symbol_name)
202+ {
203+ try {
204+ auto lib = get_wrap_library ();
205+ if (!lib) {
206+ return nullptr ;
207+ }
208+ if (!lib->has_symbol (symbol_name)) {
209+ return nullptr ;
210+ }
211+ return lib->get_symbol (symbol_name);
212+ } catch (const std::exception & e) {
213+ RMW_SET_ERROR_MSG_WITH_FORMAT_STRING (
214+ " failed to get wrapper symbol '%s' due to %s" ,
215+ symbol_name, e.what ());
216+ return nullptr ;
217+ }
218+ }
219+
178220#ifdef __cplusplus
179221extern " C"
180222{
@@ -202,6 +244,27 @@ extern "C"
202244#define ARGS_6 (t6, ...) t6 v6, EXPAND(ARGS_5(__VA_ARGS__))
203245#define ARGS_7 (t7, ...) t7 v7, EXPAND(ARGS_6(__VA_ARGS__))
204246
247+ // Macros for "wrapped function" args, allow us to prepend one extra argument more than _NR value
248+ // "tX" params are "type" for the type declaration of the argument
249+ // "vX" params are "variable" for the variable name declaration
250+ #define WARGS_0 (t0, tvoid ) t0 v0
251+ #define WARGS_1 (t1, t0 ) t1 v1, t0 v0
252+ #define WARGS_2 (t2, ...) t2 v2, EXPAND(WARGS_1(__VA_ARGS__))
253+ #define WARGS_3 (t3, ...) t3 v3, EXPAND(WARGS_2(__VA_ARGS__))
254+ #define WARGS_4 (t4, ...) t4 v4, EXPAND(WARGS_3(__VA_ARGS__))
255+ #define WARGS_5 (t5, ...) t5 v5, EXPAND(WARGS_4(__VA_ARGS__))
256+ #define WARGS_6 (t6, ...) t6 v6, EXPAND(WARGS_5(__VA_ARGS__))
257+ #define WARGS_7 (t7, ...) t7 v7, EXPAND(WARGS_6(__VA_ARGS__))
258+
259+ #define WARG_VALUES_0 (impl, ...) impl
260+ #define WARG_VALUES_1 (impl, ...) impl, EXPAND(ARG_VALUES_1(__VA_ARGS__))
261+ #define WARG_VALUES_2 (impl, ...) impl, EXPAND(ARG_VALUES_2(__VA_ARGS__))
262+ #define WARG_VALUES_3 (impl, ...) impl, EXPAND(ARG_VALUES_3(__VA_ARGS__))
263+ #define WARG_VALUES_4 (impl, ...) impl, EXPAND(ARG_VALUES_4(__VA_ARGS__))
264+ #define WARG_VALUES_5 (impl, ...) impl, EXPAND(ARG_VALUES_5(__VA_ARGS__))
265+ #define WARG_VALUES_6 (impl, ...) impl, EXPAND(ARG_VALUES_6(__VA_ARGS__))
266+ #define WARG_VALUES_7 (impl, ...) impl, EXPAND(ARG_VALUES_7(__VA_ARGS__))
267+
205268#define CALL_SYMBOL (symbol_name, ReturnType, error_value, ArgTypes, arg_values ) \
206269 if (!symbol_ ## symbol_name) { \
207270 /* only necessary for functions called before rmw_init */ \
@@ -218,8 +281,14 @@ extern "C"
218281// cppcheck-suppress preprocessorErrorDirective
219282#define RMW_INTERFACE_FN (name, ReturnType, error_value, _NR, ...) \
220283 void * symbol_ ## name = nullptr ; \
284+ void * symbol_wrap_ ## name = nullptr ; \
221285 ReturnType name (EXPAND(ARGS_ ## _NR(__VA_ARGS__))) \
222286 { \
287+ if (symbol_wrap_ ## name) { \
288+ typedef ReturnType (* WrapFunctionSignature)(EXPAND (WARGS_ ## _NR (void *, __VA_ARGS__))); \
289+ auto wrap_func = reinterpret_cast <WrapFunctionSignature>(symbol_wrap_ ## name); \
290+ return wrap_func (EXPAND (WARG_VALUES_ ## _NR (symbol_ ## name, __VA_ARGS__))); \
291+ } \
223292 CALL_SYMBOL ( \
224293 name, ReturnType, error_value, ARG_TYPES (__VA_ARGS__), \
225294 EXPAND (ARG_VALUES_ ## _NR (__VA_ARGS__))); \
@@ -788,8 +857,9 @@ RMW_INTERFACE_FN(
788857 3 , ARG_TYPES(
789858 const char *, rcutils_allocator_t *, rosidl_dynamic_typesupport_serialization_support_t *))
790859
791-
792- #define GET_SYMBOL (x ) symbol_ ## x = get_symbol(#x);
860+ #define GET_SYMBOL (x ) \
861+ symbol_ ## x = get_symbol(#x); \
862+ symbol_wrap_ ## x = get_wrap_symbol(STRINGIFY(wrap_ ## x));
793863
794864void prefetch_symbols (void )
795865{
@@ -891,6 +961,7 @@ void prefetch_symbols(void)
891961}
892962
893963void * symbol_rmw_init = nullptr ;
964+ void * symbol_wrap_rmw_init = nullptr ;
894965
895966rmw_ret_t
896967rmw_init (const rmw_init_options_t * options, rmw_context_t * context)
@@ -902,10 +973,19 @@ rmw_init(const rmw_init_options_t * options, rmw_context_t * context)
902973 if (!symbol_rmw_init) {
903974 return RMW_RET_ERROR;
904975 }
976+ if (!symbol_wrap_rmw_init) {
977+ symbol_wrap_rmw_init = get_wrap_symbol (" wrap_rmw_init" );
978+ }
979+ rmw_ret_t ret = RMW_RET_OK;
980+ if (symbol_wrap_rmw_init) {
981+ typedef rmw_ret_t (* WrapperInitSignature)(void *, const rmw_init_options_t *, rmw_context_t *);
982+ auto wrap_init_func = reinterpret_cast <WrapperInitSignature>(symbol_wrap_rmw_init);
983+ ret = wrap_init_func (get_library ().get (), options, context);
984+ }
905985
906986 typedef rmw_ret_t (* FunctionSignature)(const rmw_init_options_t *, rmw_context_t *);
907987 FunctionSignature func = reinterpret_cast <FunctionSignature>(symbol_rmw_init);
908- return func (options, context);
988+ return ret != RMW_RET_OK ? ret : func (options, context);
909989}
910990
911991#ifdef __cplusplus
0 commit comments