15
15
group TypesSwigInterface;
16
16
17
17
import "com/eprosima/fastdds/idl/templates/eprosima.stg"
18
+ import "FastCdrCommon.stg"
18
19
19
20
main(ctx, definitions) ::= <<
20
21
$fileHeader(ctx=ctx, file=[ctx.filename, ".i"], description=["This header file contains the SWIG interface of the described types in the IDL file."])$
21
22
22
- %module(moduleimport="if __import__('os').name == 'nt': import win32api; win32api.LoadLibrary('$ctx.filename$.dll')\nif __package__ or '.' in __name__:\n from . import _$ctx.filename$Wrapper\nelse:\n import _$ctx.filename$Wrapper") $ctx.filename$
23
+ %module($if(ctx.thereIsInterface)$threads="1",directors="1",$endif$moduleimport="if __import__('os').name == 'nt': import win32api; win32api.LoadLibrary('$ctx.filename$.dll')\nif __package__ or '.' in __name__:\n from . import _$ctx.filename$Wrapper\nelse:\n import _$ctx.filename$Wrapper") $ctx.filename$
24
+
25
+ $if(ctx.thereIsInterface)$
26
+ // We have enabled threads because the RPC server directors will call the target language environment
27
+ // from the C++ server threads, but we don't want the calls from the target language to release their
28
+ // locks (e.g. Python GIL) when calling the C++ methods.
29
+ // See a very nice explanation at https://github.com/swig/swig/issues/927#issuecomment-289279243
30
+ %feature("nothreadallow");
31
+ $endif$
23
32
24
33
// If using windows in debug, it would try to use python_d, which would not be found.
25
34
%begin %{
@@ -30,9 +39,16 @@ $fileHeader(ctx=ctx, file=[ctx.filename, ".i"], description=["This header file c
30
39
%}
31
40
32
41
// SWIG helper modules
42
+ $if(ctx.thereIsInterface)$
43
+ %include "exception.i"
44
+ $endif$
33
45
%include "stdint.i"
34
46
%include "std_array.i"
35
47
%include "std_map.i"
48
+ $if(ctx.thereIsInterface)$
49
+ %include "std_pair.i"
50
+ %include "std_shared_ptr.i"
51
+ $endif$
36
52
%include "std_string.i"
37
53
%include "std_vector.i"
38
54
%include "typemaps.i"
@@ -47,6 +63,11 @@ $ctx.directIncludeDependencies : {include | %include "$include$.i"}; separator="
47
63
48
64
%{
49
65
#include "$ctx.filename$.hpp"
66
+ $if(ctx.thereIsInterface)$
67
+ #include "$ctx.filename$Client.hpp"
68
+ #include "$ctx.filename$Server.hpp"
69
+ #include "$ctx.filename$ServerImpl.hpp"
70
+ $endif$
50
71
51
72
#include <fastdds/dds/core/LoanableSequence.hpp>
52
73
%}
@@ -62,6 +83,118 @@ $endif$
62
83
%import(module="fastdds") "fastdds/dds/core/LoanableTypedCollection.hpp"
63
84
%import(module="fastdds") "fastdds/dds/core/LoanableSequence.hpp"
64
85
86
+ $if(ctx.thereIsInterface)$
87
+ %import(module="fastdds") "fastdds/dds/rpc/exceptions/RpcException.hpp"
88
+ %import(module="fastdds") "fastdds/dds/rpc/exceptions/RpcOperationError.hpp"
89
+
90
+ %exception {
91
+ try
92
+ {
93
+ \$action
94
+ }
95
+ catch (const eprosima::fastdds::dds::rpc::RpcException& ex)
96
+ {
97
+ SWIG_exception(SWIG_RuntimeError, ex.what());
98
+ }
99
+ catch (const std::exception& ex)
100
+ {
101
+ SWIG_exception(SWIG_RuntimeError, ex.what());
102
+ }
103
+ catch (...)
104
+ {
105
+ SWIG_exception(SWIG_RuntimeError,"Unknown exception");
106
+ }
107
+ }
108
+
109
+ $if(ctx.thereIsOutputFeed)$
110
+ %import(module="fastdds") "fastdds/dds/rpc/interfaces/RpcServerWriter.hpp"
111
+ %ignore eprosima::fastdds::dds::rpc::RpcClientReader::read(T&);
112
+ %ignore eprosima::fastdds::dds::rpc::RpcClientReader::read(T&,eprosima::fastdds::dds::Duration_t&);
113
+ %import(module="fastdds") "fastdds/dds/rpc/interfaces/RpcClientReader.hpp"
114
+ %extend eprosima::fastdds::dds::rpc::RpcClientReader {
115
+ std::pair<bool, T> read(
116
+ const eprosima::fastdds::dds::Duration_t& timeout = eprosima::fastdds::dds::c_TimeInfinite)
117
+ {
118
+ std::pair<bool, T> ret_val{};
119
+ if (eprosima::fastdds::dds::c_TimeInfinite == timeout)
120
+ {
121
+ ret_val.first = self->read(ret_val.second);
122
+ }
123
+ else
124
+ {
125
+ ret_val.first = self->read(ret_val.second, timeout);
126
+ }
127
+ return ret_val;
128
+ }
129
+ }
130
+
131
+ $ctx.outputFeedTypes : {feed_type | $output_feed(feed_type)$}; separator="\n\n"$
132
+ $endif$
133
+
134
+ $if(ctx.thereIsNonFeedOperation)$
135
+ // Code for std::future taken from https://github.com/swig/swig/issues/1828#issuecomment-648449092
136
+ namespace eprosima::fastdds::dds::rpc
137
+ {
138
+ template <class R>
139
+ class RpcFuture {
140
+ public:
141
+ RpcFuture() noexcept;
142
+ RpcFuture(RpcFuture &&) noexcept;
143
+ RpcFuture(const RpcFuture& rhs) = delete;
144
+ ~RpcFuture();
145
+ RpcFuture& operator=(const RpcFuture& rhs) = delete;
146
+ RpcFuture& operator=(RpcFuture&&) noexcept;
147
+
148
+ // retrieving the value
149
+ R get();
150
+
151
+ // functions to check state
152
+ bool valid() const noexcept;
153
+ void wait() const;
154
+
155
+ /*
156
+ template <class Rep, class Period>
157
+ future_status wait_for(const chrono::duration<Rep, Period>& rel_time) const;
158
+ template <class Clock, class Duration>
159
+ future_status wait_until(const chrono::time_point<Clock, Duration>& abs_time) const;
160
+ */
161
+ };
162
+
163
+ }
164
+
165
+ $ctx.outputNonFeedTypes : {non_feed_type | $output_non_feed(non_feed_type)$}; separator="\n\n"$
166
+ $endif$
167
+
168
+ $if(ctx.thereIsInputFeed)$
169
+ %import(module="fastdds") "fastdds/dds/rpc/interfaces/RpcClientWriter.hpp"
170
+ %import(module="fastdds") "fastdds/dds/rpc/interfaces/RpcStatusCode.hpp"
171
+
172
+ %ignore eprosima::fastdds::dds::rpc::RpcServerReader::read(T&);
173
+ %ignore eprosima::fastdds::dds::rpc::RpcServerReader::read(T&,eprosima::fastdds::dds::Duration_t&);
174
+ %import(module="fastdds") "fastdds/dds/rpc/interfaces/RpcServerReader.hpp"
175
+ %extend eprosima::fastdds::dds::rpc::RpcServerReader {
176
+ std::pair<bool, T> read(
177
+ const eprosima::fastdds::dds::Duration_t& timeout = eprosima::fastdds::dds::c_TimeInfinite)
178
+ {
179
+ std::pair<bool, T> ret_val{};
180
+ if (eprosima::fastdds::dds::c_TimeInfinite == timeout)
181
+ {
182
+ ret_val.first = self->read(ret_val.second);
183
+ }
184
+ else
185
+ {
186
+ ret_val.first = self->read(ret_val.second, timeout);
187
+ }
188
+ return ret_val;
189
+ }
190
+ }
191
+
192
+ $ctx.inputFeedTypes : {feed_type | $input_feed(feed_type)$}; separator="\n\n"$
193
+ $endif$
194
+
195
+ %exception;
196
+ $endif$
197
+
65
198
%define %traits_penumn(Type...)
66
199
%fragment(SWIG_Traits_frag(Type),"header",
67
200
fragment="StdTraits") {
@@ -78,6 +211,11 @@ $definitions; separator="\n"$
78
211
79
212
// Include the class interfaces
80
213
%include "$ctx.filename$.hpp"
214
+ $if(ctx.thereIsInterface)$
215
+ %include "$ctx.filename$Client.hpp"
216
+ %include "$ctx.filename$Server.hpp"
217
+ %include "$ctx.filename$ServerImpl.hpp"
218
+ $endif$
81
219
82
220
// Include the corresponding TopicDataType
83
221
%include "$ctx.filename$PubSubTypes.i"
@@ -241,3 +379,65 @@ bitset_type(ctx, parent, bitset, extensions) ::= <<
241
379
enum_type(ctx, parent, enum) ::= <<
242
380
%traits_penumn(enum $enum.cppTypename$);
243
381
>>
382
+
383
+ interface(ctx, parent, interface, export_list) ::= <<
384
+
385
+ $export_list$
386
+
387
+ %shared_ptr($interface.scopedname$);
388
+ $if(!interface.annotatedAsNested)$
389
+ %shared_ptr($interface.scopedname$Server);
390
+ %extend $interface.scopedname$Server
391
+ {
392
+ void run()
393
+ {
394
+ Py_BEGIN_ALLOW_THREADS
395
+ self->run();
396
+ Py_END_ALLOW_THREADS
397
+ }
398
+ }
399
+
400
+ %shared_ptr($interface.scopedname$Server_IServerImplementation);
401
+ %shared_ptr($interface.scopedname$ServerImplementation);
402
+ %feature("director") $interface.scopedname$ServerImplementation;
403
+ $endif$
404
+ >>
405
+
406
+ output_non_feed(type) ::= <<
407
+ %shared_ptr(eprosima::fastdds::dds::rpc::RpcFuture<$type.cppTypename$>);
408
+ %template($type.formatedCppTypename$_rpc_future) eprosima::fastdds::dds::rpc::RpcFuture<$type.cppTypename$>;
409
+
410
+ $!
411
+ // Combine the typemap from shared_ptr
412
+ // https://github.com/swig/swig/blob/b96b955ca15a01f0425fb26c234528530923202a/Lib/python/boost_shared_ptr.i#L41-L44
413
+ // with the use of the 'optimal' attribute to avoid the need for a copy constructor, inspired by
414
+ // https://github.com/swig/swig/issues/1828#issuecomment-648449092
415
+ !$
416
+ %typemap(out, optimal="1") eprosima::fastdds::dds::rpc::RpcFuture<$type.cppTypename$> {
417
+ std::shared_ptr<\$1_ltype> *smartresult = new std::shared_ptr<\$1_ltype>(new \$1_ltype(\$1));
418
+ \$result = SWIG_NewPointerObj(SWIG_as_voidptr(smartresult), \$descriptor(std::shared_ptr< eprosima::fastdds::dds::rpc::RpcFuture<$type.cppTypename$\>> *), SWIG_POINTER_OWN);
419
+ }
420
+ >>
421
+
422
+ output_feed(type) ::= <<
423
+ %shared_ptr(eprosima::fastdds::dds::rpc::RpcClientReader<$type.cppTypename$>);
424
+ %template($type.formatedCppTypename$_client_reader_result) std::pair<bool, $type.cppTypename$>;
425
+ %template($type.formatedCppTypename$_client_reader) eprosima::fastdds::dds::rpc::RpcClientReader<$type.cppTypename$>;
426
+
427
+ %template($type.formatedCppTypename$_server_writer) eprosima::fastdds::dds::rpc::RpcServerWriter<$type.cppTypename$>;
428
+ >>
429
+
430
+ input_feed(type) ::= <<
431
+ %template($type.formatedCppTypename$_server_reader_result) std::pair<bool, $type.cppTypename$>;
432
+ %template($type.formatedCppTypename$_server_reader) eprosima::fastdds::dds::rpc::RpcServerReader<$type.cppTypename$>;
433
+
434
+ %shared_ptr(eprosima::fastdds::dds::rpc::RpcClientWriter<$type.cppTypename$>);
435
+ %template($type.formatedCppTypename$_rpc_client_writer) eprosima::fastdds::dds::rpc::RpcClientWriter<$type.cppTypename$>;
436
+ %typemap(in,numinputs=0) std::shared_ptr<eprosima::fastdds::dds::rpc::RpcClientWriter<$type.cppTypename$\>>& %{
437
+ \$1 = new std::shared_ptr<eprosima::fastdds::dds::rpc::RpcClientWriter<$type.cppTypename$\>>();
438
+ %}
439
+ %typemap(argout) std::shared_ptr<eprosima::fastdds::dds::rpc::RpcClientWriter<$type.cppTypename$\>>& (PyObject* tmp) %{
440
+ tmp = SWIG_NewPointerObj(\$1, \$1_descriptor, SWIG_POINTER_OWN);
441
+ \$result = SWIG_Python_AppendOutput(\$result, tmp);
442
+ %}
443
+ >>
0 commit comments