SpecStruc-BeginC++.xml 13 KB

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