Welcome to mirror list, hosted at ThFree Co, Russian Federation.

index.dok « dok - github.com/torch/cwrap.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 62a71ba1ed7c1003ef802c0554e24a7f34604c20 (plain)
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
====== Wrap package ======

The **wrap** package helps you to automate the generation of Lua/C wrappers
around existing C functions, such that these functions would be callable
from Lua. This package is used by the **torch** package, but does not depend on
anything, and could be used by anyone using Lua.

**DISCLAIMER** Before going any further, we assume the reader has a good
knowledge of how to interface C functions with Lua. A good start would be
the [[http://www.lua.org/manual/5.1|Lua reference manual]], or the book
[[http://www.inf.puc-rio.br/~roberto/pil2|Programming in Lua]].

As an example is often better than lengthy explanations, let's consider the
case of a function
<file c>
int numel(THDoubleTensor *t);
</file>
which returns the number of elements of ''t''.
Writing a complete wrapper of this function would look like:
<file c>
static int wrapper_numel(lua_State *L)
{
  THDoubleTensor *t;

  /* always good to check the number of arguments */
  if(lua_gettop(L) != 1)
    error("invalid number of arguments: <tensor> expected");

  /* check if we have a tensor on the stack */
  /* we use the luaT library, which deals with Torch objects */
  /* we assume the torch_DoubleTensor_id has been already initialized */
  t = luaT_checkudata(L, 1, torch_DoubleTensor_id);

  /* push result on stack */
  lua_pushnumber(L, numel(t));

  /* the number of returned variables */
  return 1;
}
</file>

For anybody familiar with the Lua C API, this should look very simple (and
//it is simple//, Lua has been designed for that!). Nevertheless, the
wrapper contains about 7 lines of C code, for a quite simple
function. Writing wrappers for C functions with multiple arguments, where
some of them might be optional, can become very quickly a tedious task. The
**wrap** package is here to help the process. Remember however that even
though you might be able to treat most complex cases with **wrap**,
sometimes it is also good to do everything by hand yourself!

===== High Level Interface =====

**wrap** provides only one class: ''CInterface''. Considering our easy example, a typical usage
would be:
<file lua>
require 'wrap'

interface = wrap.CInterface.new()

interface:wrap(
   "numel", -- the Lua name
   "numel", -- the C function name, here the same
   -- now we describe the 'arguments' of the C function
   -- (or possible returned values)
   {
      {name="DoubleTensor"},
      {name="int", creturned=true} -- this one is returned by the C function
   }
)

print(interface:tostring())
</file>
''CInterface'' contains only few methods. [[#CInterface.wrap|wrap()]] is
the most important one. [[#CInterface.tostring|tostring()]] returns a
string containing all the code produced until now.  The wrapper generated
by **wrap** is quite similar to what one would write by hand:
<file c>
static int wrapper_numel(lua_State *L)
{
  int narg = lua_gettop(L);
  THDoubleTensor *arg1 = NULL;
  int arg2 = 0;
  if(narg == 1
     && (arg1 = luaT_toudata(L, 1, torch_DoubleTensor_id))
    )
  {
  }
  else
    luaL_error(L, "expected arguments: DoubleTensor");
  arg2 = numel(arg1);
  lua_pushnumber(L, (lua_Number)arg2);
  return 1;
}
</file>

We know describe the few methods provided by ''CInterface''.

==== new() ====
{{anchor:CInterface.new}}

Returns a new ''CInterface''.

==== print(str) ====
{{anchor:CInterface.print}}

Add some hand-crafted code to the existing generated code. You might want to do that if your wrapper
requires manual tweaks. For e.g., in the example above, the "id" related to ''torch.DoubleTensor''
needs to be defined beforehand:
<file lua>
interface:print([[
const void* torch_DoubleTensor_id;
]])
</file>

==== luaname2wrapname(name) ====
{{anchor:CInterface.luaname2wrapname}}

This method defines the name of each generated wrapping function (like
''wrapper_numel'' in the example above), given the Lua name of a function
(say ''numel''). In general, this has little importance, as the wrapper is
a static function which is not going to be called outside the scope of the
wrap file. However, if you generate some complex wrappers, you might want
to have a control on this to avoid name clashes. The default is
<file lua>
function CInterface:luaname2wrapname(name)
   return string.format("wrapper_%s", name)
end
</file>
Changing it to something else can be easily done with (still following the example above)
<file lua>
function interface:luaname2wrapname(name)
   return string.format("my_own_naming_%s", name)
end
</file>

==== register(name) ====

Produces C code defining a
[[http://www.lua.org/manual/5.1/manual.html#luaL_Reg|luaL_Reg]] structure
(which will have the given ''name''). In the above example, calling
<file lua>
interface:register('myfuncs')
</file>
will generate the following additional code:
<file c>
static const struct luaL_Reg myfuncs [] = {
  {"numel", wrapper_numel},
  {NULL, NULL}
};
</file>

This structure is meant to be passed as argument to
[[http://www.lua.org/manual/5.1/manual.html#luaL_register|luaL_register]],
such that Lua will be aware of your new functions. For e.g., the following
would declare ''mylib.numel'' in Lua:
<file lua>
interface:print([[
luaL_register(L, "mylib", myfuncs);
]])
</file>

==== tostring() ====
{{anchor:CInterface.tostring}}

Returns a string containing all the code generated by the ''CInterface''
until now. Note that the history is not erased.

==== tofile(filename) ====
{{anchor:CInterface.tofile}}

Write in the file (named after ''filename'') all the code generated by the
''CInterface'' until now. Note that the history is not erased.

==== clearhistory() ====
{{anchor:CInterface.clearhhistory}}

Forget about all the code generated by the ''CInterface'' until now.