⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 callpolicies.html

📁 cpptcl library for ns2
💻 HTML
字号:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head>  <meta content="text/html; charset=ISO-8859-1" http-equiv="content-type">  <title>C++/Tcl</title></head><body><table style="width: 100%; text-align: left;" border="0" cellpadding="2" cellspacing="20">  <tbody>    <tr>      <td style="vertical-align: top;"><font size="+3"><span style="font-family: helvetica,arial,sans-serif; font-weight: bold; color: rgb(0, 0, 255);">C++/Tcl</span></font><br>      <span style="font-family: helvetica,arial,sans-serif; color: rgb(0, 0, 255); font-weight: bold;">AC++ library for interoperability between C++ and Tcl</span> </td>      <td style="vertical-align: top; text-align: right;"><br>      </td>    </tr>  </tbody></table><br>[<a href="objects.html">prev</a>][<a href="index.html">top</a>][<a href="goodies.html">next</a>]<br><h4>Call Policies</h4><span style="font-weight: bold;"><a name="factories"></a>Factories andsinks</span><br><br>C++ has extremely rich type system. You can see this when you exposesome free or member function:<br><br><div style="margin-left: 40px;"><code>i.def("fun", fun);</code><br></div><br>The name of the function, <code>fun</code>, is enough for the C++/Tcllibray to discover the following information:<br><ul>  <li>Whether the function returns anything and what exactly.</li>  <li>Whether it has any parameters, how many of them and what aretheir types.<br>  </li></ul>Sadly, these two pieces of information are sometimes not enough.<br>Consider the following C++ functions:<br><br><div style="margin-left: 40px;"><code>SomeClass * produce()</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; return new SomeClass();</code><br><code>}</code><br><code></code><br><code>void consume(SomeClass *p)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; // ...</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; delete p;</code><br><code>}</code><br><code></code></div><br>These two functions can be exposed this way:<br><br><div style="margin-left: 40px;"><code>i.def("produce", produce);</code><br><code>i.def("consume", consume);</code><br><code></code></div><br>After doing so, you can safely use them like here:<br><br><div style="margin-left: 40px;"><code>% set object [produce]</code><br><code>p0x807b790</code><br><code>% consume $object</code><br><code></code></div><br>The problem is that the <code>produce</code> command will not registerany new Tcl command that would be responsible for managing memberfunction calls or explicit object destruction, because, simply, it hasno idea to which class definition (in the Tcl sense, not the C++ sense)the returned object belongs. In other words, the object name that isreturned by the <code>produce</code> command has no meaning to the Tclinterpreter.<br>To solve this problem, some additional information has to be providedwhile exposing the <code>produce</code> function:<br><br><div style="margin-left: 40px;"><code>i.def("produce", produce,factory("SomeClass"));</code><br></div><br>As you see, there is additional parameter that provides hints to theC++/Tcl library. Such hints are called <span style="font-style: italic;">policies</span>.<br>The <code>factory</code> policy above provides the followinginformation:<br><ul>  <li>The objects returned by the <code>produce</code> function arecreated with the <code>new</code> expression, or by other means. Inany case - the pointer is returned.<br>  </li>  <li>These objects are meant to be handled as if they were created byregular constructor.</li>  <ul>    <li>In particular, a new command has to be registered for eachobject returned by this function.</li>    <li>This command should work as defined for the <code>"SomeClass"</code>Tcl class.<br>    </li>  </ul></ul><br>What about the consume function?<br>There is also a problem - normally, objects are destroyed by explicitcall to their <code>-delete</code> method. This call does two things:<br><ul>  <li>It <code>delete</code>s the objects (in the C++ sense), and</li>  <li>it unregisters the Tcl command associated with that object.</li></ul>We already know that the <code>consume()</code> function does thefirst thing. It is important also to do the second, otherwise the Tclinterpreter will be polluted with commands associated with non-existentobjects (any call to such a command will result in undefined behaviour,which usually means a program crash).<br>In other words, we have to provide a hint to the C++/Tcl library thatthe <code>consume()</code> function is a <span style="font-style: italic;">sink</span> for objects:<br><br><div style="margin-left: 40px;"><code>i.def("consume", consume,sink(1));</code><br></div><br>The <code>sink</code> policy above says:<br><ul>  <li>The <code>consume</code> function takes responsibility forobjects that are passed by its first (1) parameter.</li>  <li>The object will be destroyed (or otherwise managed).</li>  <li>The Tcl command associated with this object should beunregistered.</li></ul>The following is a complete example with the use of policies:<br><br><div style="margin-left: 40px;"><code>// example5.cc</code><br><code></code><br><code>#include "cpptcl.h"</code><br><code>#include &lt;string&gt;</code><br><code></code><br><code>using namespace std;</code><br><code>using namespace Tcl;</code><br><code></code><br><code>class Person</code><br><code>{</code><br><code>public:</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; Person(string const &amp;n) : name(n) {}</code><br><code></code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; void setName(string const &amp;n) { name= n; }</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; string getName() { return name; }</code><br><code></code><br><code>private:</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; string name;</code><br><code>};</code><br><code></code><br><code>// this is a factory function</code><br><code>Person * makePerson(string const &amp;name)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; return new Person(name);</code><br><code>}</code><br><code></code><br><code>// this is a sink function</code><br><code>void killPerson(Person *p)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; delete p;</code><br><code>}</code><br><code></code><br><code>CPPTCL_MODULE(Mymodule, i)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; // note that the Person class is exposedwithout any constructor</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; i.class_&lt;Person&gt;("Person", <span style="font-weight: bold;">no_init</span>)</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.def("setName", &amp;Person::setName)</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.def("getName", &amp;Person::getName);</code><br><code></code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; i.def("makePerson", makePerson, <span style="font-weight: bold;">factory("Person")</span>);</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; i.def("killPerson", killPerson, <span style="font-weight: bold;">sink(1)</span>);</code><br><code>}</code><br><code></code></div><br>Now, let's try to exercise some interactive session with this:<br><br><div style="margin-left: 40px;"><code>% load ./mymodule.so </code><br><code>% set p [Person "Maciej"]</code><br><code>invalid command name "Person"</code><br><code>% </code><br><code></code></div><br>As you see, the Tcl class <code>Person</code> has no constructor (thisis the effect of providing the <code>no_init</code> policy when theclass was exposed).<br>Let's try another way:<br><br><div style="margin-left: 40px;"><code>% set p [makePerson "John"]</code><br><code>p0x807b810</code><br><code>% $p getName</code><br><code>John</code><br><code>% </code><br><code></code></div><br>It works fine. Now:<br><br><div style="margin-left: 40px;"><code>% killPerson $p</code><br><code>% $p getName</code><br><code>invalid command name "p0x807b810"</code><br><code>% </code><br><code></code></div><br><br>Interestingly, a single function may need to combine several policiesat once:<br><br><div style="margin-left: 40px;"><code>ClassA * create(int i, ClassB*p1, string const &amp;s, ClassC *p2)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; // consume both p1 and p2 pointers</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; // and create new object:</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; return new ClassA();</code><br><code>}</code><br><code></code></div><br>This function needs to combine three policies:<br><ol>  <li>The <code>factory</code> policy, because it returns new objects.</li>  <li>The <code>sink</code> policy on its second parameter.</li>  <li>The <code>sink</code> policy on its fourth parameter.<br>  </li></ol>The following definition does it:<br><br><div style="margin-left: 40px;"><code>i.def("create", create,factory("ClassA").sink(2).sink(4));</code><br></div><br>As you see, policies can be chained. Their order is not important,apart from the fact that the <code>factory</code> policy can berelated to only one class, so it is the last <code>factory</code>policy in the chain that is effective.<br><br><br><span style="font-weight: bold;"><a name="variadic"></a>Variadicfunctions</span><br><br>Another thing that can be controlled from policies is whether thefunction is variadic (whether it can accept variable number ofarguments) or not.<br>This feature is supported for:<br><ul>  <li>free functions</li>  <li>constructors</li>  <li>class methods<br>  </li></ul>In order for the function (or constructor or method) to be variadic, <span style="font-style: italic;">both</span> of the following conditionsmust be true:<br><ol>  <li>The type of last (or the only) parameter must be <code>objectconst &amp;<br>    </code></li>  <li>The <code>variadic()</code> policy must be provided whendefining that function.</li></ol>The last formal parameter is of the generic <code>object</code> typeand it allows to retrieve both single values and lists.<br>An example may help:<br><br><div style="margin-left: 40px;"><code>void fun(int a, int b, <span style="font-weight: bold;">object const &amp;c</span>);<br><br>// later:<br></code><code>i.def("fun", fun);</code><br><code></code></div><br>Above, the fun() function is defined in the interpreter as having <span style="font-style: italic;">exactly</span> three parameters.<br>If more arguments are provided, they are discarded. If less, an erroris reported.<br>Now, consider the following change:<br><br><div style="margin-left: 40px;"><code>void fun(int a, int b, <span style="font-weight: bold;">object const &amp;c</span>);<br><br>// later:<br></code><code>i.def("fun", fun, <span style="font-weight: bold;">variadic()</span>);</code><br><code></code></div><br>With the <code>variadic()</code> policy, the function will accept:<br><ul>  <li>two integer arguments - in that case, the <code>c</code>parameter will be an empty object</li>  <li>three arguments - in that case, <code>c</code> will have thevalue of the third argument</li>  <li>more - <code>c</code> will be a list of all arguments except thefirst two integer values.</li></ul>Similarly, a constructor with variable list of parameters may bedefined as:<br><br><div style="margin-left: 40px;"><code>class MyClass</code><br><code>{</code><br><code>public:</code><br><code>&nbsp;&nbsp;&nbsp; MyClass(int a, <span style="font-weight: bold;">object const &amp;b</span>);</code><br><code>&nbsp;&nbsp;&nbsp; void fun();</code><br><code>};</code><br><code></code><br><code>// later:</code><br><code>i.class_&lt;MyClass&gt;("MyClass", init&lt;int, <span style="font-weight: bold;">object const &amp;</span>&gt;(), <span style="font-weight: bold;">variadic()</span>)</code><br><code>&nbsp;&nbsp;&nbsp; .def("fun", &amp;MyClass::fun);</code><br><code></code></div><br>Note that the last parameter in the constructor has type <code>objectconst &amp;</code> and that the <code>variadic()</code> policy wasprovided.<br>This constructor will accept 1, 2 or more arguments.<br><br>Of course, the variadic class methods can be defined in the same way:<br><br><div style="margin-left: 40px;"><code>class MyClass</code><br><code>{</code><br><code>public:</code><br><code></code><code>&nbsp;&nbsp;&nbsp; void fun(<span style="font-weight: bold;">object const &amp;a</span>);</code><br><code>};</code><br><code></code><br><code>// later:</code><br><code>i.class_&lt;MyClass&gt;("MyClass")</code><br><code>&nbsp;&nbsp;&nbsp; .def("fun", &amp;MyClass::fun, <span style="font-weight: bold;">variadic()</span>);</code><br><code></code></div><br>As you see, the special, last parameter may be the only one, orpreceded by any number of "normal" parameters.<br><br>The possibility to define a variadic function is currently the only wayto write commands that accept more than 9 arguments.<br><br>The <code>variadic()</code> policy may be combined (in any order) withother policies.<br><br>The following is a full example of module that defines one variadicfunction:<br><br><div style="margin-left: 40px;"><code>#include "cpptcl.h"</code><br><code></code><br><code>using namespace Tcl;</code><br><code></code><br><code>int sumAll(object const &amp;argv)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; interpreter i(argv.get_interp(), false);</code><br><code></code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; int sum = 0;</code><br><code></code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; size_t argc = argv.length(i);</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; for (size_t indx = 0; indx != argc;++indx)</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; {</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objecto(argv.at(i, indx));</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sum +=o.get&lt;int&gt;(i);</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; }</code><br><code></code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; return sum;</code><br><code>}</code><br><code></code><br><code>CPPTCL_MODULE(Mymodule, i)</code><br><code>{</code><br><code>&nbsp;&nbsp;&nbsp;&nbsp; i.def("sum", sumAll, variadic());</code><br><code>}</code><br><code></code></div><br>This module can be used from the Tcl interpreter like here;<br><br><div style="margin-left: 40px;"><code>% load ./mymodule.so </code><br><code>% sum</code><br><code>0</code><br><code>% sum 5</code><br><code>5</code><br><code>% sum 5 6 7</code><br><code>18</code><br><code>% </code><br><code></code></div><br><br>[<a href="objects.html">prev</a>][<a href="index.html">top</a>][<a href="goodies.html">next</a>]<br><br><hr style="width: 100%; height: 2px;">Copyright &copy; 2004-2006,MaciejSobczak<br><br></body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -