dub 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/History.txt +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +53 -0
- data/Rakefile +58 -0
- data/dub.gemspec +194 -0
- data/lib/dub/argument.rb +261 -0
- data/lib/dub/entities_unescape.rb +16 -0
- data/lib/dub/function.rb +111 -0
- data/lib/dub/function_group.rb +74 -0
- data/lib/dub/generator.rb +15 -0
- data/lib/dub/group.rb +10 -0
- data/lib/dub/klass.rb +231 -0
- data/lib/dub/lua/class.cpp.erb +75 -0
- data/lib/dub/lua/class_gen.rb +78 -0
- data/lib/dub/lua/function.cpp.erb +4 -0
- data/lib/dub/lua/function_gen.rb +223 -0
- data/lib/dub/lua/group.cpp.erb +10 -0
- data/lib/dub/lua/lua_cpp_helper.h +141 -0
- data/lib/dub/lua/namespace.cpp.erb +35 -0
- data/lib/dub/lua/namespace_gen.rb +86 -0
- data/lib/dub/lua.rb +24 -0
- data/lib/dub/member_extraction.rb +88 -0
- data/lib/dub/namespace.rb +276 -0
- data/lib/dub/parser.rb +46 -0
- data/lib/dub/templates/lua_template.erb +21 -0
- data/lib/dub/version.rb +3 -0
- data/lib/dub.rb +26 -0
- data/test/argument_test.rb +423 -0
- data/test/fixtures/app/CMakeLists.txt +54 -0
- data/test/fixtures/app/Doxyfile +1600 -0
- data/test/fixtures/app/bindings/all_lua.cpp +299 -0
- data/test/fixtures/app/include/matrix.h +123 -0
- data/test/fixtures/app/make_lua_bindings.rb +13 -0
- data/test/fixtures/app/vendor/lua/CMakeLists.txt +25 -0
- data/test/fixtures/app/vendor/lua/COPYRIGHT +34 -0
- data/test/fixtures/app/vendor/lua/HISTORY +183 -0
- data/test/fixtures/app/vendor/lua/INSTALL +99 -0
- data/test/fixtures/app/vendor/lua/Makefile +183 -0
- data/test/fixtures/app/vendor/lua/README +37 -0
- data/test/fixtures/app/vendor/lua/lapi.c +1080 -0
- data/test/fixtures/app/vendor/lua/lapi.h +16 -0
- data/test/fixtures/app/vendor/lua/lauxlib.c +653 -0
- data/test/fixtures/app/vendor/lua/lauxlib.h +174 -0
- data/test/fixtures/app/vendor/lua/lbaselib.c +643 -0
- data/test/fixtures/app/vendor/lua/lcode.c +839 -0
- data/test/fixtures/app/vendor/lua/lcode.h +76 -0
- data/test/fixtures/app/vendor/lua/ldblib.c +397 -0
- data/test/fixtures/app/vendor/lua/ldebug.c +622 -0
- data/test/fixtures/app/vendor/lua/ldebug.h +33 -0
- data/test/fixtures/app/vendor/lua/ldo.c +516 -0
- data/test/fixtures/app/vendor/lua/ldo.h +57 -0
- data/test/fixtures/app/vendor/lua/ldump.c +164 -0
- data/test/fixtures/app/vendor/lua/lfunc.c +174 -0
- data/test/fixtures/app/vendor/lua/lfunc.h +34 -0
- data/test/fixtures/app/vendor/lua/lgc.c +711 -0
- data/test/fixtures/app/vendor/lua/lgc.h +110 -0
- data/test/fixtures/app/vendor/lua/liblua.a +0 -0
- data/test/fixtures/app/vendor/lua/linit.c +38 -0
- data/test/fixtures/app/vendor/lua/liolib.c +532 -0
- data/test/fixtures/app/vendor/lua/llex.c +461 -0
- data/test/fixtures/app/vendor/lua/llex.h +81 -0
- data/test/fixtures/app/vendor/lua/llimits.h +128 -0
- data/test/fixtures/app/vendor/lua/lmathlib.c +263 -0
- data/test/fixtures/app/vendor/lua/lmem.c +86 -0
- data/test/fixtures/app/vendor/lua/lmem.h +49 -0
- data/test/fixtures/app/vendor/lua/loadlib.c +664 -0
- data/test/fixtures/app/vendor/lua/lobject.c +214 -0
- data/test/fixtures/app/vendor/lua/lobject.h +381 -0
- data/test/fixtures/app/vendor/lua/lopcodes.c +102 -0
- data/test/fixtures/app/vendor/lua/lopcodes.h +268 -0
- data/test/fixtures/app/vendor/lua/loslib.c +244 -0
- data/test/fixtures/app/vendor/lua/lparser.c +1337 -0
- data/test/fixtures/app/vendor/lua/lparser.h +82 -0
- data/test/fixtures/app/vendor/lua/lstate.c +214 -0
- data/test/fixtures/app/vendor/lua/lstate.h +168 -0
- data/test/fixtures/app/vendor/lua/lstring.c +111 -0
- data/test/fixtures/app/vendor/lua/lstring.h +31 -0
- data/test/fixtures/app/vendor/lua/lstrlib.c +868 -0
- data/test/fixtures/app/vendor/lua/ltable.c +588 -0
- data/test/fixtures/app/vendor/lua/ltable.h +40 -0
- data/test/fixtures/app/vendor/lua/ltablib.c +278 -0
- data/test/fixtures/app/vendor/lua/ltm.c +75 -0
- data/test/fixtures/app/vendor/lua/ltm.h +54 -0
- data/test/fixtures/app/vendor/lua/lua.c +695 -0
- data/test/fixtures/app/vendor/lua/lua.h +385 -0
- data/test/fixtures/app/vendor/lua/lua_dub_helper.h +77 -0
- data/test/fixtures/app/vendor/lua/luac +0 -0
- data/test/fixtures/app/vendor/lua/luac.c +200 -0
- data/test/fixtures/app/vendor/lua/luaconf.h +762 -0
- data/test/fixtures/app/vendor/lua/lualib.h +53 -0
- data/test/fixtures/app/vendor/lua/lundump.c +223 -0
- data/test/fixtures/app/vendor/lua/lundump.h +36 -0
- data/test/fixtures/app/vendor/lua/lvm.c +765 -0
- data/test/fixtures/app/vendor/lua/lvm.h +36 -0
- data/test/fixtures/app/vendor/lua/lzio.c +82 -0
- data/test/fixtures/app/vendor/lua/lzio.h +67 -0
- data/test/fixtures/app/vendor/lua/matrix.h +102 -0
- data/test/fixtures/app/vendor/lua/print.c +227 -0
- data/test/fixtures/app/vendor/lua/test/README +26 -0
- data/test/fixtures/app/vendor/lua/test/bisect.lua +27 -0
- data/test/fixtures/app/vendor/lua/test/cf.lua +16 -0
- data/test/fixtures/app/vendor/lua/test/echo.lua +5 -0
- data/test/fixtures/app/vendor/lua/test/env.lua +7 -0
- data/test/fixtures/app/vendor/lua/test/factorial.lua +32 -0
- data/test/fixtures/app/vendor/lua/test/fib.lua +40 -0
- data/test/fixtures/app/vendor/lua/test/fibfor.lua +13 -0
- data/test/fixtures/app/vendor/lua/test/globals.lua +13 -0
- data/test/fixtures/app/vendor/lua/test/hello.lua +3 -0
- data/test/fixtures/app/vendor/lua/test/life.lua +111 -0
- data/test/fixtures/app/vendor/lua/test/luac.lua +7 -0
- data/test/fixtures/app/vendor/lua/test/printf.lua +7 -0
- data/test/fixtures/app/vendor/lua/test/readonly.lua +12 -0
- data/test/fixtures/app/vendor/lua/test/sieve.lua +29 -0
- data/test/fixtures/app/vendor/lua/test/sort.lua +66 -0
- data/test/fixtures/app/vendor/lua/test/table.lua +12 -0
- data/test/fixtures/app/vendor/lua/test/trace-calls.lua +32 -0
- data/test/fixtures/app/vendor/lua/test/trace-globals.lua +38 -0
- data/test/fixtures/app/vendor/lua/test/xd.lua +14 -0
- data/test/fixtures/app/xml/classdub_1_1_matrix.xml +239 -0
- data/test/fixtures/app/xml/classdub_1_1_t_mat.xml +233 -0
- data/test/fixtures/app/xml/combine.xslt +15 -0
- data/test/fixtures/app/xml/compound.xsd +814 -0
- data/test/fixtures/app/xml/dir_53661a2bdeb1d55e60581a7e15deb763.xml +12 -0
- data/test/fixtures/app/xml/index.xml +42 -0
- data/test/fixtures/app/xml/index.xsd +66 -0
- data/test/fixtures/app/xml/matrix_8h.xml +149 -0
- data/test/fixtures/app/xml/namespacedub.xml +41 -0
- data/test/fixtures/classcv_1_1_mat.xml +1996 -0
- data/test/fixtures/classcv_1_1_point__.xml +341 -0
- data/test/fixtures/classcv_1_1_size__.xml +270 -0
- data/test/fixtures/group___magic_type.xml +406 -0
- data/test/fixtures/namespacecv.xml +12659 -0
- data/test/function_group_test.rb +15 -0
- data/test/function_test.rb +252 -0
- data/test/group_test.rb +155 -0
- data/test/helper.rb +34 -0
- data/test/klass_test.rb +297 -0
- data/test/lua_function_gen_test.rb +179 -0
- data/test/namespace_test.rb +220 -0
- data/test/parser_test.rb +36 -0
- metadata +216 -0
@@ -0,0 +1,223 @@
|
|
1
|
+
require 'dub/generator'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Dub
|
5
|
+
module Lua
|
6
|
+
class FunctionGen < Dub::Generator
|
7
|
+
FLOAT_TYPES = [
|
8
|
+
'float',
|
9
|
+
'double',
|
10
|
+
'size_t',
|
11
|
+
'unsigned int',
|
12
|
+
'uint',
|
13
|
+
]
|
14
|
+
|
15
|
+
INT_TYPES = [
|
16
|
+
'int',
|
17
|
+
'size_t',
|
18
|
+
'unsigned int',
|
19
|
+
'uint',
|
20
|
+
'bool',
|
21
|
+
'uchar'
|
22
|
+
]
|
23
|
+
|
24
|
+
def initialize
|
25
|
+
@function_template = ::ERB.new(File.read(File.join(File.dirname(__FILE__), 'function.cpp.erb')))
|
26
|
+
@group_template = ::ERB.new(File.read(File.join(File.dirname(__FILE__), 'group.cpp.erb')))
|
27
|
+
end
|
28
|
+
|
29
|
+
# Produce bindings for a group of overloaded functions
|
30
|
+
def group(group)
|
31
|
+
@group = group
|
32
|
+
@group_template.result(binding)
|
33
|
+
end
|
34
|
+
|
35
|
+
def function(function)
|
36
|
+
@function = function
|
37
|
+
@function_template.result(binding)
|
38
|
+
end
|
39
|
+
|
40
|
+
def function_generator
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
def namespace_generator
|
45
|
+
Dub::Lua.namespace_generator
|
46
|
+
end
|
47
|
+
|
48
|
+
# Create a switch to choose the correct method from argument types (overloaded functions)
|
49
|
+
def switch(hash_or_function, depth = 1)
|
50
|
+
if hash_or_function.kind_of?(Function)
|
51
|
+
method_call(hash_or_function)
|
52
|
+
else
|
53
|
+
res = []
|
54
|
+
res << "type__ = lua_type(L, #{depth});" unless depth == 1
|
55
|
+
else_prefix = ''
|
56
|
+
default_sub_group = nil
|
57
|
+
hash_or_function.each do |type, sub_group|
|
58
|
+
default_sub_group = sub_group
|
59
|
+
case type
|
60
|
+
when :number
|
61
|
+
res << "#{else_prefix}if (type__ == LUA_TNUMBER) {"
|
62
|
+
when :string
|
63
|
+
res << "#{else_prefix}if (type__ == LUA_TSTRING) {"
|
64
|
+
when nil
|
65
|
+
res << "#{else_prefix}if (type__ == LUA_TNONE) {"
|
66
|
+
else
|
67
|
+
res << "#{else_prefix}if (type__ == LUA_TUSERDATA && is_userdata(L, #{depth}, \"#{type}\")) {"
|
68
|
+
end
|
69
|
+
|
70
|
+
res << indent(switch(sub_group, depth + 1), 2)
|
71
|
+
|
72
|
+
else_prefix = '} else '
|
73
|
+
end
|
74
|
+
|
75
|
+
last = default_sub_group.kind_of?(Hash) ? flatten_hash(default_sub_group).last : default_sub_group
|
76
|
+
|
77
|
+
res << "} else {"
|
78
|
+
res << " // use any to raise errors"
|
79
|
+
res << indent(method_call(last), 2)
|
80
|
+
res << "}"
|
81
|
+
res.join("\n")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def signature(func, overloaded_index = nil)
|
86
|
+
"static int #{method_name(func, overloaded_index)}(lua_State *L)"
|
87
|
+
end
|
88
|
+
|
89
|
+
def body(func)
|
90
|
+
res = []
|
91
|
+
|
92
|
+
if func.member_method? && !func.constructor?
|
93
|
+
klass = func.parent
|
94
|
+
res << "#{klass.name} *self__ = *((#{klass.name}**)luaL_checkudata(L, 1, #{klass.id_name.inspect}));"
|
95
|
+
res << "lua_remove(L, 1);"
|
96
|
+
end
|
97
|
+
|
98
|
+
if func.has_default_arguments?
|
99
|
+
res << "int top__ = lua_gettop(L);"
|
100
|
+
if return_value = func.return_value
|
101
|
+
res << "#{return_value.create_type} retval__;"
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
if_indent = 0
|
106
|
+
func.arguments.each_with_index do |arg, i|
|
107
|
+
if arg.has_default?
|
108
|
+
res << indent("if (top__ < #{i+1}) {", if_indent)
|
109
|
+
res << indent(" #{call_string(func, i)}", if_indent)
|
110
|
+
res << indent("} else {", if_indent)
|
111
|
+
if_indent += 2
|
112
|
+
end
|
113
|
+
res << indent(get_arg(arg, i + 1), if_indent)
|
114
|
+
end
|
115
|
+
res << indent(call_string(func, func.arguments.count), if_indent)
|
116
|
+
while if_indent > 0
|
117
|
+
if_indent -= 2
|
118
|
+
res << indent("}", if_indent)
|
119
|
+
end
|
120
|
+
|
121
|
+
res << return_value(func)
|
122
|
+
res.join("\n")
|
123
|
+
end
|
124
|
+
|
125
|
+
def method_name(func, overloaded_index = nil)
|
126
|
+
overloaded_index ||= func.overloaded_index
|
127
|
+
overloaded_index = '' if overloaded_index == 0
|
128
|
+
"#{func.prefix}_#{func.name}#{overloaded_index}"
|
129
|
+
end
|
130
|
+
|
131
|
+
def method_call(func)
|
132
|
+
"return #{method_name(func)}(L);"
|
133
|
+
end
|
134
|
+
|
135
|
+
def call_string(func, upto_arg)
|
136
|
+
if upto_arg == 0
|
137
|
+
call_string = "#{func.name}();"
|
138
|
+
else
|
139
|
+
call_string = "#{func.name}(#{func.arguments[0..(upto_arg-1)].map{|arg| arg.in_call_type}.join(', ')});"
|
140
|
+
end
|
141
|
+
|
142
|
+
if func.constructor?
|
143
|
+
call_string = "new #{call_string}"
|
144
|
+
elsif func.member_method?
|
145
|
+
call_string = "self__->#{call_string}"
|
146
|
+
end
|
147
|
+
|
148
|
+
|
149
|
+
if return_value = func.return_value
|
150
|
+
if func.has_default_arguments?
|
151
|
+
"retval__ = #{call_string}"
|
152
|
+
else
|
153
|
+
"#{return_value.create_type} retval__ = #{call_string}"
|
154
|
+
end
|
155
|
+
else
|
156
|
+
call_string
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def return_value(func)
|
161
|
+
res = []
|
162
|
+
if return_value = func.return_value
|
163
|
+
case Argument.type_group(return_value)
|
164
|
+
when :number
|
165
|
+
res << "lua_pushnumber(L, retval__);"
|
166
|
+
when :string
|
167
|
+
raise "Not supported yet"
|
168
|
+
else
|
169
|
+
if func.constructor?
|
170
|
+
prefix = func.klass.prefix
|
171
|
+
else
|
172
|
+
prefix = func.prefix
|
173
|
+
end
|
174
|
+
res << "lua_pushclass<#{return_value.type}>(L, retval__, \"#{return_value.id_name}\");"
|
175
|
+
end
|
176
|
+
res << "return 1;"
|
177
|
+
else
|
178
|
+
res << "return 0;"
|
179
|
+
end
|
180
|
+
res.join("\n")
|
181
|
+
end
|
182
|
+
|
183
|
+
# Get argument and verify type
|
184
|
+
# // luaL_argcheck could be better to report errors like "expected Mat"
|
185
|
+
def get_arg(arg, stack_pos)
|
186
|
+
type_def = "#{arg.create_type}#{arg.name}#{arg.array_suffix}"
|
187
|
+
if arg.is_native?
|
188
|
+
if arg.is_pointer?
|
189
|
+
if arg.type == 'char'
|
190
|
+
type_def = "const #{type_def}" unless arg.is_const?
|
191
|
+
"#{type_def} = luaL_checkstring(L, #{stack_pos});"
|
192
|
+
else
|
193
|
+
# retrieve by using a table accessor
|
194
|
+
# TODO: we should have a hint on required sizes !
|
195
|
+
"\nDubArgPointer<#{arg.type}> ptr_#{arg.name};\n" +
|
196
|
+
"#{type_def} = ptr_#{arg.name}(L, #{stack_pos});"
|
197
|
+
end
|
198
|
+
else
|
199
|
+
if FLOAT_TYPES.include?(arg.type)
|
200
|
+
"#{type_def} = luaL_checknumber(L, #{stack_pos});"
|
201
|
+
elsif INT_TYPES.include?(arg.type)
|
202
|
+
"#{type_def} = luaL_checkint(L, #{stack_pos});"
|
203
|
+
else
|
204
|
+
raise "Unsuported type: #{arg.type}"
|
205
|
+
end
|
206
|
+
end
|
207
|
+
else
|
208
|
+
"#{type_def} = *((#{arg.create_type}*)luaL_checkudata(L, #{stack_pos}, #{arg.id_name.inspect}));"
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def flatten_hash(hash)
|
213
|
+
hash.each do |k, v|
|
214
|
+
if v.kind_of?(Hash)
|
215
|
+
hash[k] = flatten_hash(v)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
hash.to_a.flatten
|
219
|
+
end
|
220
|
+
|
221
|
+
end # FunctionGen
|
222
|
+
end # Lua
|
223
|
+
end # Dub
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<% @group.members.each do |f| %>
|
2
|
+
<%= function(f) %>
|
3
|
+
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
/** Overloaded function chooser for <%= @group.name %>(...) */
|
7
|
+
<%= signature(@group.first, 0) %> {
|
8
|
+
int type__ = lua_type(L, 1);
|
9
|
+
<%= indent(switch(Argument.decision_tree(@group.members)), 2) %>
|
10
|
+
}
|
@@ -0,0 +1,141 @@
|
|
1
|
+
|
2
|
+
#ifndef DOXY_GENERATOR_LIB_DOXY_GENERATOR_INCLUDE_LUA_DOXY_HELPER_H_
|
3
|
+
#define DOXY_GENERATOR_LIB_DOXY_GENERATOR_INCLUDE_LUA_DOXY_HELPER_H_
|
4
|
+
|
5
|
+
#include <stdlib.h> // malloc
|
6
|
+
|
7
|
+
#ifdef __cplusplus
|
8
|
+
extern "C" {
|
9
|
+
#endif
|
10
|
+
// We need C linkage because lua lib is compiled as C code
|
11
|
+
#include "lua.h"
|
12
|
+
#include "lauxlib.h"
|
13
|
+
|
14
|
+
#ifdef __cplusplus
|
15
|
+
}
|
16
|
+
#endif
|
17
|
+
/** ======================================== lua_pushclass */
|
18
|
+
|
19
|
+
/** Push a custom type on the stack.
|
20
|
+
* Since the value is passed as a pointer, we assume it has been created
|
21
|
+
* using 'new' and Lua can safely call delete when it needs to garbage-
|
22
|
+
* -collect it.
|
23
|
+
*/
|
24
|
+
template<class T>
|
25
|
+
void lua_pushclass(lua_State *L, T *ptr, const char *type_name) {
|
26
|
+
T **userdata = (T**)lua_newuserdata(L, sizeof(T*));
|
27
|
+
*userdata = ptr;
|
28
|
+
|
29
|
+
// the userdata is now on top of the stack
|
30
|
+
|
31
|
+
// set metatable (contains methods)
|
32
|
+
luaL_getmetatable(L, type_name);
|
33
|
+
lua_setmetatable(L, -2);
|
34
|
+
}
|
35
|
+
|
36
|
+
/** Push a custom type on the stack.
|
37
|
+
* Since the value is passed by value, we have to allocate a copy
|
38
|
+
* using 'new' so that Lua can keep it.
|
39
|
+
*/
|
40
|
+
template<class T>
|
41
|
+
void lua_pushclass(lua_State *L, T &val, const char *type_name) {
|
42
|
+
T *val_ptr = new T(val);
|
43
|
+
lua_pushclass<T>(L, val_ptr, type_name);
|
44
|
+
}
|
45
|
+
|
46
|
+
/** ======================================== DubArgPointer */
|
47
|
+
|
48
|
+
/** This class is a helper to provide pointer to data from
|
49
|
+
* Lua to C (but maybe it's not a good idea).
|
50
|
+
*/
|
51
|
+
template<class T>
|
52
|
+
class DubArgPointer {
|
53
|
+
public:
|
54
|
+
DubArgPointer() : data(NULL) {}
|
55
|
+
|
56
|
+
~DubArgPointer() {
|
57
|
+
if (data) free(data);
|
58
|
+
}
|
59
|
+
|
60
|
+
// TODO: we should have a hint on required sizes !
|
61
|
+
T *operator()(lua_State *L, int index) {
|
62
|
+
if (!lua_istable(L, index)) throw 1;
|
63
|
+
|
64
|
+
size_t size = lua_objlen(L, index);
|
65
|
+
if (size == 0) return NULL;
|
66
|
+
|
67
|
+
data = (T*)malloc(size * sizeof(T));
|
68
|
+
if (!data) throw 1;
|
69
|
+
|
70
|
+
for(size_t i=0; i < size; ++i) {
|
71
|
+
data[i] = get_value_at(L, index, i+1);
|
72
|
+
}
|
73
|
+
return data;
|
74
|
+
}
|
75
|
+
|
76
|
+
private:
|
77
|
+
T get_value_at(lua_State *L, int table_index, int index) {
|
78
|
+
lua_pushinteger(L, index + 1);
|
79
|
+
lua_gettable(L, index);
|
80
|
+
T value = luaL_checknumber(L, -1);
|
81
|
+
lua_pop(L, 1);
|
82
|
+
return value;
|
83
|
+
}
|
84
|
+
|
85
|
+
T *data;
|
86
|
+
};
|
87
|
+
|
88
|
+
/** ======================================== is_userdata */
|
89
|
+
|
90
|
+
inline bool is_userdata(lua_State *L, int index, const char *tname) {
|
91
|
+
void *p = lua_touserdata(L, index);
|
92
|
+
if (p != NULL) { /* value is a userdata? */
|
93
|
+
if (lua_getmetatable(L, index)) { /* does it have a metatable? */
|
94
|
+
lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */
|
95
|
+
if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */
|
96
|
+
lua_pop(L, 2); /* remove both metatables */
|
97
|
+
// type match
|
98
|
+
return true;
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
// type does not match
|
103
|
+
return false;
|
104
|
+
}
|
105
|
+
|
106
|
+
/** ======================================== register_constants */
|
107
|
+
|
108
|
+
|
109
|
+
typedef struct lua_constants_Reg {
|
110
|
+
const char *name;
|
111
|
+
double constant;
|
112
|
+
} lua_constants_Reg;
|
113
|
+
|
114
|
+
inline int libsize (const lua_constants_Reg *l) {
|
115
|
+
int size = 0;
|
116
|
+
for (; l->name; l++) size++;
|
117
|
+
return size;
|
118
|
+
}
|
119
|
+
|
120
|
+
inline void register_constants(lua_State *L, const char *name_space, const lua_constants_Reg *l) {
|
121
|
+
if (name_space) {
|
122
|
+
/* compute size hint for new table. */
|
123
|
+
int size = libsize(l);
|
124
|
+
|
125
|
+
/* try global variable (and create one if it does not exist) */
|
126
|
+
if (luaL_findtable(L, LUA_GLOBALSINDEX, name_space, size) != NULL)
|
127
|
+
luaL_error(L, "name conflict for module " LUA_QS, name_space);
|
128
|
+
|
129
|
+
/* found name_space in global index ==> stack -1 */
|
130
|
+
}
|
131
|
+
for (; l->name; l++) {
|
132
|
+
/* push each constant into the name_space (stack position = -1)*/
|
133
|
+
lua_pushnumber(L, l->constant);
|
134
|
+
lua_setfield(L, -2, l->name);
|
135
|
+
}
|
136
|
+
/* pop name_space */
|
137
|
+
lua_pop(L, 1);
|
138
|
+
}
|
139
|
+
|
140
|
+
|
141
|
+
#endif // DOXY_GENERATOR_LIB_DOXY_GENERATOR_INCLUDE_LUA_DOXY_HELPER_H_
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#include "<%= @namespace.header %>"
|
2
|
+
|
3
|
+
#include "lua_cpp_helper.h"
|
4
|
+
|
5
|
+
using namespace <%= @namespace.name %>;
|
6
|
+
|
7
|
+
<% if @namespace.members; @namespace.members.each do |function| %>
|
8
|
+
|
9
|
+
<%= function %>
|
10
|
+
|
11
|
+
<% end; end %>
|
12
|
+
|
13
|
+
// Register namespace
|
14
|
+
|
15
|
+
|
16
|
+
static const struct luaL_Reg <%= @namespace.name %>_functions[] = {
|
17
|
+
<%= indent(functions_registration, 2) %>,
|
18
|
+
{NULL, NULL},
|
19
|
+
};
|
20
|
+
|
21
|
+
<% if @namespace.has_constants? %>
|
22
|
+
static const struct lua_constants_Reg <%= @namespace.name %>_namespace_constants[] = {
|
23
|
+
<%= indent(constants_registration, 2) %>,
|
24
|
+
{NULL, NULL},
|
25
|
+
};
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
void luaopen_<%= @namespace.lib_name %>(lua_State *L) {
|
29
|
+
// register functions
|
30
|
+
luaL_register(L, <%= @namespace.name.inspect %>, <%= @namespace.name %>_functions);
|
31
|
+
<% if @namespace.has_constants? %>
|
32
|
+
// register namespace enums
|
33
|
+
register_constants(L, <%= @namespace.id_name.inspect %>, <%= @namespace.name %>_namespace_constants);
|
34
|
+
<% end %>
|
35
|
+
}
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'dub/generator'
|
2
|
+
require 'erb'
|
3
|
+
|
4
|
+
module Dub
|
5
|
+
module Lua
|
6
|
+
class NamespaceGen < Dub::Generator
|
7
|
+
def initialize
|
8
|
+
@namespace_template = ::ERB.new(File.read(File.join(File.dirname(__FILE__), 'namespace.cpp.erb')))
|
9
|
+
end
|
10
|
+
|
11
|
+
def namespace(namespace)
|
12
|
+
@namespace = namespace
|
13
|
+
@namespace_template.result(binding)
|
14
|
+
end
|
15
|
+
|
16
|
+
def class_generator
|
17
|
+
Lua.class_generator
|
18
|
+
end
|
19
|
+
|
20
|
+
def function_generator
|
21
|
+
Lua.function_generator
|
22
|
+
end
|
23
|
+
|
24
|
+
def functions_registration(namespace = @namespace)
|
25
|
+
(namespace.members || []).map do |method|
|
26
|
+
"{%-32s, #{method.method_name(0)}}" % method.name.inspect
|
27
|
+
end.join(",\n")
|
28
|
+
end
|
29
|
+
|
30
|
+
def constants_registration(namespace = @namespace)
|
31
|
+
res = []
|
32
|
+
if namespace.has_enums?
|
33
|
+
res << namespace.enums.map do |name|
|
34
|
+
"{%-32s, #{namespace.full_type}::#{name}}" % name.inspect
|
35
|
+
end.join(",\n")
|
36
|
+
end
|
37
|
+
|
38
|
+
if namespace.has_defines?
|
39
|
+
res << namespace.defines.map do |name|
|
40
|
+
"{%-32s, #{name}}" % name.inspect
|
41
|
+
end.join(",\n")
|
42
|
+
end
|
43
|
+
|
44
|
+
same = namespace.enums & namespace.defines
|
45
|
+
unless same.empty?
|
46
|
+
# Should never happen (not sure if it would compile ok in the first place)
|
47
|
+
puts "Warning: the following are present both as enum and define: #{same.inspect}"
|
48
|
+
end
|
49
|
+
res.join(",\n\n")
|
50
|
+
end
|
51
|
+
|
52
|
+
def members_list(all_members, ignore_list = [])
|
53
|
+
list = all_members.map do |member_or_group|
|
54
|
+
if ignore_list.include?(member_or_group.name)
|
55
|
+
nil
|
56
|
+
elsif member_or_group.kind_of?(Array)
|
57
|
+
members_list(member_or_group)
|
58
|
+
elsif ignore_member?(member_or_group)
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
member_or_group
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
list.compact!
|
66
|
+
list == [] ? nil : list
|
67
|
+
end
|
68
|
+
|
69
|
+
def ignore_member?(member)
|
70
|
+
if member.name =~ /^~/ || # do not build constructor
|
71
|
+
member.name =~ /^operator/ || # no conversion operators
|
72
|
+
member.original_signature =~ />/ || # no complex types in signature
|
73
|
+
member.has_array_arguments? ||
|
74
|
+
member.vararg? ||
|
75
|
+
member.original_signature =~ /void\s+\*/
|
76
|
+
true # ignore
|
77
|
+
elsif return_value = member.return_value
|
78
|
+
return_value.type =~ />$/ || # no complex return types
|
79
|
+
return_value.is_native? && member.return_value.is_pointer?
|
80
|
+
else
|
81
|
+
false # ok, do not ignore
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/dub/lua.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'dub/lua/function_gen'
|
2
|
+
require 'dub/lua/namespace_gen'
|
3
|
+
require 'dub/lua/class_gen'
|
4
|
+
|
5
|
+
module Dub
|
6
|
+
module Lua
|
7
|
+
def self.function_generator
|
8
|
+
@@function_generator ||= Dub::Lua::FunctionGen.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.class_generator
|
12
|
+
@@class_generator ||= Dub::Lua::ClassGen.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.namespace_generator
|
16
|
+
@@namespace_generator ||= Dub::Lua::NamespaceGen.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.bind(object)
|
20
|
+
object.bind(self)
|
21
|
+
object
|
22
|
+
end
|
23
|
+
end # Lua
|
24
|
+
end # Dub
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'dub/function'
|
2
|
+
require 'dub/function_group'
|
3
|
+
require 'dub/klass'
|
4
|
+
|
5
|
+
module Dub
|
6
|
+
class Klass
|
7
|
+
end
|
8
|
+
|
9
|
+
# This module is used by Namespace and Klass to extract member functions
|
10
|
+
module MemberExtraction
|
11
|
+
def members_prefix
|
12
|
+
@name
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_members
|
16
|
+
@members_hash = {}
|
17
|
+
@t_members_hash = {}
|
18
|
+
# TODO: template functions
|
19
|
+
(@xml/'memberdef').each do |member|
|
20
|
+
Dub.logger.info "Parsing #{member.name}"
|
21
|
+
name = (member/"name").innerHTML
|
22
|
+
if (member/'templateparamlist').first
|
23
|
+
insert_member(member, name, @t_members_hash)
|
24
|
+
else
|
25
|
+
insert_member(member, name, @members_hash)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def insert_member(member, name, destination)
|
31
|
+
if destination[name].kind_of?(Array)
|
32
|
+
destination[name] << member
|
33
|
+
elsif first_member = destination[name]
|
34
|
+
destination[name] = [first_member, member]
|
35
|
+
else
|
36
|
+
destination[name] = member
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def member(name)
|
41
|
+
get_member(name.to_s)
|
42
|
+
end
|
43
|
+
|
44
|
+
def members
|
45
|
+
@members ||= begin
|
46
|
+
list = []
|
47
|
+
@members_hash.each do |name, member|
|
48
|
+
list << get_member(name)
|
49
|
+
end
|
50
|
+
list.compact!
|
51
|
+
list.sort
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Lazy construction of members
|
56
|
+
def get_member(name)
|
57
|
+
if member_or_group = @members_hash[name]
|
58
|
+
if member_or_group.kind_of?(Array)
|
59
|
+
if member_or_group.first.kind_of?(Hpricot::Elem)
|
60
|
+
list = Dub::FunctionGroup.new(self)
|
61
|
+
member_or_group.each_with_index do |m,i|
|
62
|
+
list << make_member(name, m, i + 1)
|
63
|
+
end
|
64
|
+
member_or_group = list.compact
|
65
|
+
member_or_group = nil if member_or_group == []
|
66
|
+
end
|
67
|
+
elsif member_or_group.kind_of?(Hpricot::Elem)
|
68
|
+
@members_hash[name] = member_or_group = make_member(name, member_or_group)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
member_or_group
|
72
|
+
end
|
73
|
+
|
74
|
+
def make_member(name, member, overloaded_index = nil)
|
75
|
+
case member[:kind]
|
76
|
+
when 'function'
|
77
|
+
Dub.logger.info "Building #{members_prefix}::#{name}"
|
78
|
+
Function.new(self, name, member, members_prefix, overloaded_index)
|
79
|
+
when 'class'
|
80
|
+
Dub.logger.info "Building #{members_prefix}::#{name}"
|
81
|
+
Klass.new(self, name, member, members_prefix)
|
82
|
+
else
|
83
|
+
# not supported: ignore
|
84
|
+
nil
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end # Dub
|