C++/Tcl A C++ library for interoperability between C++ and Tcl |
i.def("fun", fun);
fun
, is enough for the C++/Tcl
libray to discover the following information:SomeClass * produce()
{
return new SomeClass();
}
void consume(SomeClass *p)
{
// ...
delete p;
}
i.def("produce", produce);
i.def("consume", consume);
% set object [produce]
p0x807b790
% consume $object
produce
command will not register
any new Tcl command that would be responsible for managing member
function calls or explicit object destruction, because, simply, it has
no idea to which class definition (in the Tcl sense, not the C++ sense)
the returned object belongs. In other words, the object name that is
returned by the produce
command has no meaning to the Tcl
interpreter.produce
function:i.def("produce", produce,
factory("SomeClass"));
factory
policy above provides the following
information:produce
function are
created with the new
expression, or by other means. In
any case - the pointer is returned."SomeClass"
Tcl class.-delete
method. This call does two things:delete
s the objects (in the C++ sense), andconsume()
function does the
first thing. It is important also to do the second, otherwise the Tcl
interpreter will be polluted with commands associated with non-existent
objects (any call to such a command will result in undefined behaviour,
which usually means a program crash).consume()
function is a sink for objects:i.def("consume", consume,
sink(1));
sink
policy above says:consume
function takes responsibility for
objects that are passed by its first (1) parameter.// example5.cc
#include "cpptcl.h"
#include <string>
using namespace std;
using namespace Tcl;
class Person
{
public:
Person(string const &n) : name(n) {}
void setName(string const &n) { name
= n; }
string getName() { return name; }
private:
string name;
};
// this is a factory function
Person * makePerson(string const &name)
{
return new Person(name);
}
// this is a sink function
void killPerson(Person *p)
{
delete p;
}
CPPTCL_MODULE(Mymodule, i)
{
// note that the Person class is exposed
without any constructor
i.class_<Person>("Person", no_init)
.def("setName", &Person::setName)
.def("getName", &Person::getName);
i.def("makePerson", makePerson, factory("Person"));
i.def("killPerson", killPerson, sink(1));
}
% load ./mymodule.so
% set p [Person "Maciej"]
invalid command name "Person"
%
Person
has no constructor (this
is the effect of providing the no_init
policy when the
class was exposed).% set p [makePerson "John"]
p0x807b810
% $p getName
John
%
% killPerson $p
% $p getName
invalid command name "p0x807b810"
%
ClassA * create(int i, ClassB
*p1, string const &s, ClassC *p2)
{
// consume both p1 and p2 pointers
// and create new object:
return new ClassA();
}
factory
policy, because it returns new objects.sink
policy on its second parameter.sink
policy on its fourth parameter.i.def("create", create,
factory("ClassA").sink(2).sink(4));
factory
policy can be
related to only one class, so it is the last factory
policy in the chain that is effective.object
const &
variadic()
policy must be provided when
defining that function.object
type
and it allows to retrieve both single values and lists.void fun(int a, int b, object const &c);
// later:
i.def("fun", fun);
void fun(int a, int b, object const &c);
// later:
i.def("fun", fun, variadic());
variadic()
policy, the function will accept:c
parameter will be an empty objectc
will have the
value of the third argumentc
will be a list of all arguments except the
first two integer values.class MyClass
{
public:
MyClass(int a, object const &b);
void fun();
};
// later:
i.class_<MyClass>("MyClass", init<int, object const &>(), variadic())
.def("fun", &MyClass::fun);
object
const &
and that the variadic()
policy was
provided.class MyClass
{
public:
void fun(object const &a);
};
// later:
i.class_<MyClass>("MyClass")
.def("fun", &MyClass::fun, variadic());
variadic()
policy may be combined (in any order) with
other policies.#include "cpptcl.h"
using namespace Tcl;
int sumAll(object const &argv)
{
interpreter i(argv.get_interp(), false);
int sum = 0;
size_t argc = argv.length(i);
for (size_t indx = 0; indx != argc;
++indx)
{
object
o(argv.at(i, indx));
sum +=
o.get<int>(i);
}
return sum;
}
CPPTCL_MODULE(Mymodule, i)
{
i.def("sum", sumAll, variadic());
}
% load ./mymodule.so
% sum
0
% sum 5
5
% sum 5 6 7
18
%