/
Sample.html
234 lines (168 loc) · 14 KB
/
Sample.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
<!DOCTYPE html>
<html>
<head>
<title>
Sample Plugin
</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<link href="../../../3rdparty/googleCodePrettify/prettify.css" rel="stylesheet" type="text/css"/>
<link href="../../res/stylesheet.css" rel="stylesheet" type="text/css"/>
<script src="../../../3rdparty/googleCodePrettify/prettify.js" type="text/javascript"></script>
<script src="../../../3rdparty/jQuery/jquery.js" type="text/javascript"></script>
<script src="../../../res/common.js" type="text/javascript"></script>
<script src="../../res/menu.js" type="text/javascript"></script>
</head>
<body onload="prettyPrint();" ondragstart="return false;" ondrop="return false;">
<script type="text/javascript">
headerAndContentsMenu("Sample Plugin", "../../..");
</script>
<p>
The purpose of this plugin is to give other plugins access to a simple <code>add()</code> function, which could then be used as follows:
</p>
<pre class="prettyprint">...
#include "<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleutilities.h"><code>sampleutilities.h</code></a>"
...
double addResult = Sample::add(3.0, 5.0);
...</pre>
<div class="section">
File structure
</div>
<pre><a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src">src</a>
├─ <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src/sampleglobal.h">sampleglobal.h</a>
├─ <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src/sampleplugin.cpp">sampleplugin.cpp</a>
├─ <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src/sampleplugin.h">sampleplugin.h</a>
├─ <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src/sampleplugin.json">sampleplugin.json</a>
├─ <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src/sampleutilities.cpp">sampleutilities.cpp</a>
└─ <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/src/sampleutilities.h">sampleutilities.h</a>
<a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/CMakeLists.txt">CMakeLists.txt</a></pre>
<div class="section">
Category
</div>
<p>
The first thing we need to do is to decide on the category of our plugin (click <a href="index.html#Category">here</a> for some information on categories). Our plugin is aimed at helping people who want to learn how to write plugins for OpenCOR. So, it should be in the <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/">Sample</a> category. This means that its code can be found under <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/"><code>[OpenCOR]/src/plugins/sample/Sample/</code></a>.
</p>
<div class="section">
Interfaces
</div>
<p>
All our plugin does is to make its <code>add()</code> function available to other plugins, so there is no need for our plugin to interact with OpenCOR and, therefore, no need to implement any interface.
</p>
<div class="section">
CMake project
</div>
<p>
To build our plugin, we need a <code>CMakeLists.txt</code> file (click <a href="index.html#CMake project">here</a> for some information on CMake and plugins in OpenCOR), which contents is:
</p>
<pre class="prettyprint linenums">PROJECT(SamplePlugin)
# Add the plugin
ADD_PLUGIN(Sample
SOURCES
<a href="https://github.com/opencor/opencor/blob/master/src/plugins/plugininfo.cpp"><code>../../plugininfo.cpp</code></a>
<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.cpp"><code>src/sampleplugin.cpp</code></a>
<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleutilities.cpp"><code>src/sampleutilities.cpp</code></a>
HEADERS_MOC
<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.h"><code>src/sampleplugin.h</code></a>
QT_MODULES
Core
)</pre>
<p>
The first line specifies the name of the CMake project for our <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/">Sample</a> plugin, i.e. <code>SamplePlugin</code>. Then, we have a call to the <code>ADD_PLUGIN()</code> macro (line 5), which is defined in <a href="https://github.com/opencor/opencor/blob/master/cmake/common.cmake"><code>common.cmake</code></a>. Different types of parameters are passed to it (<code>SOURCES</code>, <code>HEADERS_MOC</code> and <code>QT_MODULES</code> at lines 6, 11 and 13, respectively), followed by the parameters themselves.
</p>
<p>
As for any plugin, our <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/">Sample</a> plugin must reference <a href="https://github.com/opencor/opencor/blob/master/src/plugins/plugininfo.cpp"><code>plugininfo.cpp</code></a> (line 7), so that it can provide some <a href="index.html#Basic information">basic information</a> about itself (more on this below). <code>.cpp</code> files that contain the plugin's implementation code must also be referenced (lines 9 and 10). (Note that they start with <code>sample</code>, i.e. the name of the plugin in lower case. This convention is used throughout OpenCOR's code to ensure that there are no name clashes between plugins' files.) All header files that define at least one class that uses the <code>Q_OBJECT</code> macro must also be referenced. <code>sampleplugin.h</code> is one such file (see below) and is therefore referenced (line 12). To make it easier to write (and to maintain) <code>#include</code> statements, we provide <code>src</code> as an include directory (line 14). Finally, OpenCOR uses the <a href="https://www.qt.io/">Qt</a> framework, so even though our <a href="https://github.com/opencor/opencor/tree/master/src/plugins/sample/Sample/">Sample</a> plugin is very minimal, we must reference both the <code>Core</code> module and the <code>QtCore</code> library (lines 16 and 18, respectively).
</p>
<div class="section">
Plugin information
</div>
<p>
We want our plugin to be recognisable by OpenCOR, which means that it must provide some <a href="index.html#Plugin information">plugin information</a>. <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.cpp"><code>sampleplugin.cpp</code></a> therefore contains a C function that is called by OpenCOR to retrieve some <a href="index.html#Basic information">basic information</a> about our plugin. That function is declared in <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.h"><code>sampleplugin.h</code></a>, which is also where our <a href="index.html#Plugin class">plugin class</a> is defined:
</p>
<pre class="prettyprint linenums:28">#include "<a href="https://github.com/opencor/opencor/blob/master/src/plugins/plugininfo.h"><code>plugininfo.h</code></a>"
//==============================================================================
namespace OpenCOR {
namespace Sample {
//==============================================================================
PLUGININFO_FUNC SamplePluginInfo();
//==============================================================================
class SamplePlugin : public QObject
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "OpenCOR.SamplePlugin" FILE "<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.json"><code>sampleplugin.json</code></a>")
};
//==============================================================================
} // namespace Sample
} // namespace OpenCOR</pre>
<p>
We need to know about the data structure of our <a href="index.html#Basic information">basic information</a>, so we include <a href="https://github.com/opencor/opencor/blob/master/src/plugins/plugininfo.h"><code>plugininfo.h</code></a> (line 28). Then, we declare our C function (line 37). Finally, we have the definition of our <a href="index.html#Plugin class">plugin class</a> (lines 41-46). The call to the <code>Q_PLUGIN_METADATA()</code> macro (line 45) requires to pass both an IID (<code>OpenCOR.SamplePlugin</code>) and the name of a <a href="http://www.json.org/">JSON</a> file (<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.json"><code>sampleplugin.json</code></a>). As mentioned <a href="index.html#.json file">here</a>, the JSON file simply references the name of our plugin class (<code>SamplePlugin</code>):
</p>
<pre class="prettyprint linenums">{
"Keys": [ "SamplePlugin" ]
}</pre>
<p>
Next, we have our <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.cpp"><code>sampleplugin.cpp</code></a> file, which contents is:
</p>
<pre class="prettyprint linenums:24">#include "<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleplugin.h"><code>sampleplugin.h</code></a>"
//==============================================================================
namespace OpenCOR {
namespace Sample {
//==============================================================================
PLUGININFO_FUNC SamplePluginInfo()
{
Descriptions descriptions;
descriptions.insert("en", QString::fromUtf8("a plugin that provides an addition function."));
descriptions.insert("fr", QString::fromUtf8("une extension qui fournit une fonction d'addition."));
return new PluginInfo(PluginInfo::Sample, false, false,
QStringList(),
descriptions);
}
//==============================================================================
} // namespace Sample
} // namespace OpenCOR</pre>
<p>
We start by including our header file (line 24). Then, lines 33-43 contain the body of our C function . The first thing it does is to create an instance of <code>Descriptions</code> on the stack (line 35). This instance is used to provide a multilingual description of our plugin (here, both in English and in French; lines 37 and 38). Then, it creates and returns an instance of <code>PluginInfo</code> on the heap (lines 40-42), which contains the <a href="index.html#Basic information">basic information</a> needed by OpenCOR to identify our plugin. This includes our plugin's category (<code>PluginInfo::Sample</code>; line 40), whether it is selectable (<code>false</code>; line 40), whether it offers direct <a href="https://en.wikipedia.org/wiki/Command-line_interface">CLI</a> support (<code>false</code>; line 40), our plugin's direct dependencies (none, so <code>QStringList()</code>; line 41) and its multilingual description (<code>descriptions</code>; line 42).
</p>
<p class="note">
the returned <code>PluginInfo</code> object gets deleted by OpenCOR. So, no need to worry about it.
</p>
<div class="section">
Plugin specific
</div>
<p>
Finally, we need to deal with our plugin's <code>add()</code> function. It is declared in <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleutilities.h"><code>sampleutilities.h</code></a>:
</p>
<pre class="prettyprint linenums:28">#include "<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleglobal.h"><code>sampleglobal.h</code></a>"
//==============================================================================
namespace OpenCOR {
namespace Sample {
//==============================================================================
double SAMPLE_EXPORT add(const double &pNb1, const double &pNb2);
//==============================================================================
} // namespace Sample
} // namespace OpenCOR</pre>
<p>
We start by including <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleglobal.h"><code>sampleglobal.h</code></a> (line 28). This header file defines the <code>SAMPLE_EXPORT</code> macro (click <a href="index.html#Global header file">here</a> for some information on plugins' global header file in OpenCOR), which we use to declare our plugin's <code>add()</code> function (line 37).
</p>
<p>
The implementation our plugin's <code>add()</code> function can be found in <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleutilities.cpp"><code>sampleutilities.cpp</code></a>:
</p>
<pre class="prettyprint linenums:24">#include "<a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleutilities.h"><code>sampleutilities.h</code></a>"
//==============================================================================
namespace OpenCOR {
namespace Sample {
//==============================================================================
double add(const double &pNb1, const double &pNb2)
{
// Return the sum of the two given numbers
return pNb1+pNb2;
}
//==============================================================================
} // namespace Sample
} // namespace OpenCOR</pre>
<p>
We start by including <a href="https://github.com/opencor/opencor/blob/master/src/plugins/sample/Sample/src/sampleutilities.h"><code>sampleutilities.h</code></a> (line 24). Then, we have a straightforward implementation of our plugin's <code>add()</code> function (lines 33-38).
</p>
<script type="text/javascript">
copyright("../../..");
</script>
</body>
</html>