SpecStruc-BeginC++.xml 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE sect1 PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
  3. "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
  4. <sect1 id="BEGINCplus_Structure">
  5. <title>BEGINC++ Structure<indexterm>
  6. <primary>BEGINC++ Structure</primary>
  7. </indexterm></title>
  8. <para><emphasis>resulttype funcname </emphasis><emphasis
  9. role="bold">(</emphasis><emphasis> parameterlist </emphasis><emphasis
  10. role="bold">) := BEGINC++<indexterm>
  11. <primary>BEGINC++</primary>
  12. </indexterm></emphasis><emphasis role="bold">
  13. </emphasis><emphasis></emphasis></para>
  14. <para><emphasis> code</emphasis><emphasis role="bold"> </emphasis></para>
  15. <para><emphasis role="bold">ENDC++<indexterm>
  16. <primary>ENDC++</primary>
  17. </indexterm>;</emphasis></para>
  18. <informaltable colsep="1" frame="all" rowsep="1">
  19. <tgroup cols="2">
  20. <colspec align="left" colwidth="122.40pt" />
  21. <colspec />
  22. <tbody>
  23. <row>
  24. <entry><emphasis>resulttype</emphasis></entry>
  25. <entry>The ECL return value type of the C++ function.</entry>
  26. </row>
  27. <row>
  28. <entry><emphasis>funcname</emphasis></entry>
  29. <entry><para>The ECL definition name of the function.</para></entry>
  30. </row>
  31. <row>
  32. <entry><emphasis>parameterlist</emphasis></entry>
  33. <entry>A comma separated list of the parameters to pass to the
  34. <emphasis>function</emphasis>.</entry>
  35. </row>
  36. <row>
  37. <entry><emphasis>code</emphasis></entry>
  38. <entry>The C++ function source code.</entry>
  39. </row>
  40. </tbody>
  41. </tgroup>
  42. </informaltable>
  43. <para>The <emphasis role="bold">BEGINC++ </emphasis>structure makes it
  44. possible to add in-line C++ code to your ECL. This is useful where string or
  45. bit processing would be complicated in ECL, and would be more easily done in
  46. C++, typically for a one-off use. For more commonly used C++ code, writing a
  47. plugin would be a better solution (see the <emphasis role="bold">External
  48. Service Implementation</emphasis> discussion).</para>
  49. <para>The implementation must be written to be thread safe and any calls to
  50. external libraries must be made to thread safe versions of those
  51. libraries.</para>
  52. <para><emphasis role="bold">WARNING: This feature could create memory
  53. corruption and/or security issues, so great care and forethought are
  54. advised—consult with Technical Support before using.</emphasis></para>
  55. <sect2 id="ECL_to_Cplus_Mapping">
  56. <title>ECL to C++ Mapping</title>
  57. <para>Types are passed as follows:</para>
  58. <programlisting>//The following typedefs are used below:
  59. typedef unsigned size32_t;
  60. typedef wchar_t UChar; [ unsigned short in linux ]</programlisting>
  61. <para>The following list describes the mappings from ECL to C++. For
  62. embedded C++ the parameters are always converted to lower case, and
  63. capitalized in conjunctions (see below).</para>
  64. <programlisting><emphasis role="bold">ECL C++ [Linux in brackets]</emphasis>
  65. BOOOLEAN xyz bool xyz
  66. INTEGER1 xyz signed char xyz
  67. INTEGER2 xyz int16_t xyz
  68. INTEGER4 xyz int32_t xyz
  69. INTEGER8 xyz signed __int64 xyz [ long long ]
  70. UNSIGNED1 xyz unsigned char xyz
  71. UNSIGNED2 xyz uint16_t xyz
  72. UNSIGNED4 xyz uint32_t xyz
  73. UNSIGNED8 xyz unsigned __int64 xyz [ unsigned long long xyz ]
  74. REAL4 xyz float xyz
  75. REAL/REAL8 xyz double xyz
  76. DATA xyz size32_t lenXyz, void * xyz
  77. STRING xyz size32_t lenXyz, char * xyz
  78. VARSTRING xyz char * xyz;
  79. QSTRING xyz size32_t lenXyz, char * xyz
  80. UNICODE xyz size32_t lenXyz, UChar * xyz
  81. VARUNICODE xyz UChar * xyz
  82. DATA&lt;nn&gt; xyz void * xyz
  83. STRING&lt;nn&gt; xyz char * xyz
  84. QSTRING&lt;nn&gt; xyz char * xyz
  85. UNICODE&lt;nn&gt; xyz UChar * xyz
  86. SET OF ... xyz bool isAllXyz, size32_t lenXyz, void * xyz</programlisting>
  87. <para>Note that strings of unknown length are passed differently from
  88. those with a known length. A variable length input string is passed as a
  89. number of characters, not the size (i.e. qstring/unicode), followed by a
  90. pointer to the data, like this (size32_t is an UNSIGNED4):</para>
  91. <programlisting>STRING ABC -&gt; size32_t lenAbc, const char * abc;
  92. UNICODE ABC -&gt; size32_t lenABC, const UChar * abc;</programlisting>
  93. <para>A dataset is passed as a size/pointer pair. The length gives the
  94. size of the following dataset in bytes. The same naming convention is
  95. used:</para>
  96. <programlisting>DATASET(r) ABC -&gt; size32_t lenAbc, const void * abc
  97. The rows are accessed as x+0, x + length(row1), x + length(row1) + length(row2)
  98. LINKCOUNTED DATASET(r) ABC -&gt; size32_t countAbc, const byte * * abc
  99. The rows are accessed as x[0], x[1], x[2]
  100. </programlisting>
  101. <para>NOTE: variable length strings within a record are stored as a 4 byte
  102. number of characters, followed by the string data.</para>
  103. <para>Sets are passed as a set of parameters (all, size, pointer):</para>
  104. <programlisting>SET OF UNSIGNED4 ABC -&gt; bool isAllAbc, size32_t lenAbc, const void * abc</programlisting>
  105. <para>Return types are handled as C++ functions returning the same types
  106. with some exceptions. The exceptions have some extra initial parameters to
  107. return the results in:</para>
  108. <programlisting><emphasis role="bold">ECL C++ [Linux in brackets]</emphasis>
  109. DATA xyz size32_t &amp; __lenResult, void * &amp; __result
  110. STRING xyz size32_t &amp; __lenResult, char * &amp; __result
  111. CONST STRING xyz size32_t lenXyz, const char * xyz
  112. QSTRING xyz size32_t &amp; __lenResult, char * &amp; __result
  113. UNICODE xyz size32_t &amp; __lenResult, UChar * &amp; __result
  114. CONST UNICODE xyz size32_t &amp; __lenResult, const UChar * &amp; __result
  115. DATA&lt;nn&gt; xyz void * __result
  116. STRING&lt;nn&gt; xyz char * __result
  117. QSTRING&lt;nn&gt; xyz char * __result
  118. UNICODE&lt;nn&gt; xyz UChar * __result
  119. SET OF ... xyz bool __isAllResult, size32_t &amp; __lenResult, void * &amp; __result
  120. DATASET(r) size32_t &amp; __lenResult, void * &amp; __result
  121. LINKCOUNTED DATASET(r)
  122. size32_t &amp; __countResult, byte * * &amp; __result
  123. STREAMED DATASET(r)
  124. returns a pointer to an IRowStream interface
  125. (see the eclhelper.hpp include file for the definition)</programlisting>
  126. <para>For example,</para>
  127. <programlisting>STRING process(STRING value, INTEGER4 len)</programlisting>
  128. <para>has the prototype:</para>
  129. <programlisting>void process(size32_t &amp; __lenResult, char * &amp; __result,
  130. size32_t lenValue, char * value, int len);</programlisting>
  131. <para>A function that takes a string parameter should also have the type
  132. prefixed by <emphasis role="bold">const</emphasis> in the ECL code so that
  133. modern compilers don't report errors when constant strings are passed to
  134. the function.</para>
  135. <programlisting>BOOLEAN isUpper(const string mystring) := BEGINC++
  136. size_t i=0;
  137. while (i &lt; lenMystring)
  138. {
  139. if (!isupper((byte)mystring[i]))
  140. return false;
  141. i++;
  142. }
  143. return true;
  144. ENDC++;
  145. isUpper('JIM');
  146. </programlisting>
  147. </sect2>
  148. <sect2 id="BeginCPP_Available_Options">
  149. <title>Available Options</title>
  150. <informaltable colsep="1" frame="all" rowsep="1">
  151. <tgroup cols="2">
  152. <colspec align="left" colwidth="122.40pt" />
  153. <colspec />
  154. <tbody>
  155. <row>
  156. <entry><emphasis role="bold">#option pure</emphasis></entry>
  157. <entry>By default, embedded C++ functions are assumed to have
  158. side-effects, which means the generated code won't be as efficient
  159. as it might be since the calls can't be shared. Adding #option
  160. pure inside the embedded C++ <emphasis>code</emphasis> causes it
  161. to be treated as a pure function without side effects.</entry>
  162. </row>
  163. <row>
  164. <entry><emphasis role="bold">#option once</emphasis></entry>
  165. <entry>Indicates the function has no side effects and is evaluated
  166. at query execution time, even if the parameters are constant,
  167. allowing the optimizer to make more efficient calls to the
  168. function in some cases.</entry>
  169. </row>
  170. <row>
  171. <entry><emphasis role="bold">#option action</emphasis></entry>
  172. <entry>Indicates side effects, requiring the optimizer to keep all
  173. calls to the function.</entry>
  174. </row>
  175. <row>
  176. <entry><emphasis role="bold">#body</emphasis></entry>
  177. <entry>Delimits the beginning of executable code. All
  178. <emphasis>code</emphasis> that precedes #body (such as #include)
  179. is generated outside the function definition; all code that
  180. follows it is generated inside the function definition.</entry>
  181. </row>
  182. </tbody>
  183. </tgroup>
  184. </informaltable>
  185. <para>Example:</para>
  186. <programlisting>//static int add(int x,int y) {
  187. INTEGER4 add(INTEGER4 x, INTEGER4 y) := BEGINC++
  188. #option pure
  189. return x + y;
  190. ENDC++;
  191. OUTPUT(add(10,20));
  192. //static void reverseString(size32_t &amp; __lenResult,char * &amp; __result,
  193. // size32_t lenValue,char * value) {
  194. STRING reverseString(STRING value) := BEGINC++
  195. size32_t len = lenValue;
  196. char * out = (char *)rtlMalloc(len);
  197. for (unsigned i= 0; i &lt; len; i++)
  198. out[i] = value[len-1-i];
  199. __lenResult = len;
  200. __result = out;
  201. ENDC++;
  202. OUTPUT(reverseString('Kevin'));
  203. // This is a function returning an unknown length string via the
  204. // special reference parameters __lenResult and __result
  205. //this function demonstrates #body, allowing #include to be used
  206. BOOLEAN nocaseInList(STRING search,
  207. SET OF STRING values) := BEGINC++
  208. #include &lt;string.h&gt;
  209. #body
  210. if (isAllValues)
  211. return true;
  212. const byte * cur = (const byte *)values;
  213. const byte * end = cur + lenValues;
  214. while (cur != end)
  215. {
  216. unsigned len = *(unsigned *)cur;
  217. cur += sizeof(unsigned);
  218. if (lenSearch == len &amp;&amp; memicmp(search, cur, len) == 0)
  219. return true;
  220. cur += len;
  221. }
  222. return false;
  223. ENDC++;
  224. //and another example, generating a variable number of Xes
  225. STRING buildString(INTEGER4 value) := BEGINC++
  226. char * out = (char *)rtlMalloc(value);
  227. for (unsigned i= 0; i &lt; value; i++)
  228. out[i] = 'X';
  229. __lenResult = value;
  230. __result = out;
  231. ENDC++;
  232. //examples of embedded, LINKCOUNTED, and STREAMED DATASETs
  233. inRec := { unsigned id };
  234. doneRec := { unsigned4 execid };
  235. out1rec := { unsigned id; };
  236. out2rec := { real id; };
  237. DATASET(doneRec) doSomethingNasty(DATASET(inRec) input) := BEGINC++
  238. __lenResult = 4;
  239. __result = rtlMalloc(8);
  240. *(unsigned *)__result = 91823;
  241. ENDC++;
  242. DATASET(out1Rec) extractResult1(doneRec done) := BEGINC++
  243. const unsigned id = *(unsigned *)done;
  244. const unsigned cnt = 10;
  245. __lenResult = cnt * sizeof(unsigned __int64);
  246. __result = rtlMalloc(__lenResult);
  247. for (unsigned i=0; i &lt; cnt; i++)
  248. ((unsigned __int64 *)__result)[i] = id + i + 1;
  249. ENDC++;
  250. LINKCOUNTED DATASET(out2Rec) extractResult2(doneRec done) := BEGINC++
  251. const unsigned id = *(unsigned *)done;
  252. const unsigned cnt = 10;
  253. __countResult = cnt;
  254. __result = _resultAllocator-&gt;createRowset(cnt);
  255. for (unsigned i=0; i &lt; cnt; i++)
  256. {
  257. size32_t allocSize;
  258. void * row = _resultAllocator-&gt;createRow(allocSize);
  259. *(double *)row = id + i + 1;
  260. __result[i] = (byte *)_resultAllocator-&gt;finalizeRow(allocSize, row, allocSize);
  261. }
  262. ENDC++;
  263. STREAMED DATASET(out1Rec) extractResult3(doneRec done) := BEGINC++
  264. class myStream : public IRowStream, public RtlCInterface
  265. {
  266. public:
  267. myStream(IEngineRowAllocator * _allocator, unsigned _id) : allocator(_allocator), id(_id), idx(0) {}
  268. RTLIMPLEMENT_IINTERFACE
  269. virtual const void *nextRow()
  270. {
  271. if (idx &gt;= 10)
  272. return NULL;
  273. size32_t allocSize;
  274. void * row = allocator-&gt;createRow(allocSize);
  275. *(unsigned __int64 *)row = id + ++idx;
  276. return allocator-&gt;finalizeRow(allocSize, row, allocSize);
  277. }
  278. virtual void stop() {}
  279. private:
  280. unsigned id;
  281. unsigned idx;
  282. Linked&lt;IEngineRowAllocator&gt; allocator;
  283. };
  284. #body
  285. const unsigned id = *(unsigned *)done;
  286. return new myStream(_resultAllocator, id);
  287. ENDC++;
  288. ds := DATASET([1,2,3,4], inRec);
  289. processed := doSomethingNasty(ds);
  290. out1 := NORMALIZE(processed, extractResult1(LEFT), TRANSFORM(RIGHT));
  291. out2 := NORMALIZE(processed, extractResult2(LEFT), TRANSFORM(RIGHT));
  292. out3 := NORMALIZE(processed, extractResult3(LEFT), TRANSFORM(RIGHT));
  293. SEQUENTIAL(OUTPUT(out1),OUTPUT(out2),OUTPUT(out3));
  294. </programlisting>
  295. <para>See Also: <link linkend="External_Service_Implementation">External
  296. Service Implementation</link>, <link linkend="EMBED_Structure">EMBED
  297. Structure</link></para>
  298. </sect2>
  299. </sect1>