easy-swig 1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/MIT_LICENSE +19 -0
- data/README.md +86 -0
- data/lib/apinodes/api_attribute.rb +6 -0
- data/lib/apinodes/api_class.rb +207 -0
- data/lib/apinodes/api_enum.rb +10 -0
- data/lib/apinodes/api_function.rb +13 -0
- data/lib/apinodes/api_group.rb +13 -0
- data/lib/apinodes/api_method.rb +12 -0
- data/lib/apinodes/api_namespace.rb +104 -0
- data/lib/apinodes/api_node.rb +109 -0
- data/lib/apinodes/api_variable.rb +12 -0
- data/lib/apinodes/inc_file.rb +118 -0
- data/lib/config.rb +56 -0
- data/lib/csharp/csharp_features.rb +100 -0
- data/lib/csharp/generators/csharp_class_generator.rb +14 -0
- data/lib/csharp/generators/csharp_generator.rb +17 -0
- data/lib/csharp/generators/csharp_namespace_generator.rb +33 -0
- data/lib/easy-swig-cli.rb +143 -0
- data/lib/easy-swig.rb +71 -0
- data/lib/features.rb +39 -0
- data/lib/generators/class_generator.rb +209 -0
- data/lib/generators/generator.rb +124 -0
- data/lib/generators/generator_util.rb +135 -0
- data/lib/generators/hfile_generator.rb +56 -0
- data/lib/generators/namespace_generator.rb +58 -0
- data/lib/generators/properties.rb +13 -0
- data/lib/readers/csv_parser.rb +127 -0
- data/lib/tasks/doxygen_task.rb +28 -0
- data/lib/tasks/generate_task.rb +85 -0
- data/lib/tasks/hfiles_manager.rb +86 -0
- data/lib/tasks/swig_task.rb +69 -0
- data/lib/util/logger.rb +36 -0
- data/lib/util/print.rb +72 -0
- data/lib/util/query.rb +136 -0
- data/lib/util/utilities.rb +101 -0
- data/spec/accessors/accessors_spec.rb +45 -0
- data/spec/anonymousEnums/anonymous_enums_spec.rb +49 -0
- data/spec/friends/friends_spec.rb +45 -0
- data/spec/innerclasses/innerclasses_spec.rb +48 -0
- data/spec/namespacePrefixes/namespace_prefixes_spec.rb +39 -0
- data/spec/squish/squish_spec.rb +40 -0
- data/spec/subdirectories/subdirectories_spec.rb +41 -0
- data/spec/templates/templates_spec.rb +34 -0
- metadata +107 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
require_relative '../lib/easy-swig'
|
5
|
+
|
6
|
+
options = {}
|
7
|
+
|
8
|
+
opt_parser = OptionParser.new do |opt|
|
9
|
+
opt.banner = "Welcome to Easy Swig - SWIG made easy!!"
|
10
|
+
opt.banner = "Usage: easy-swig COMMAND [OPTIONS]"
|
11
|
+
opt.separator ""
|
12
|
+
opt.separator "Commands (Use given options to override defaults)"
|
13
|
+
opt.separator " doxygen: Parses header files (.h) and generates XMLs using Doxygen. Tune with --input, --doxy, --name, --html"
|
14
|
+
opt.separator " generate: Generates SWIG Interface Files from XMLs. Tune with --csv, --doxy, --gen, --name, --lang, --custom,"
|
15
|
+
opt.separator " swig: Runs SWIG against the specified interface files. Tune with --target, --input, --output, --include, --lang"
|
16
|
+
opt.separator ""
|
17
|
+
opt.separator "Options"
|
18
|
+
|
19
|
+
opt.on("-d", "--default DIRECTORY", "Uses the given directory for default values for all needed options") do |dir|
|
20
|
+
options[:default] = dir
|
21
|
+
end
|
22
|
+
|
23
|
+
opt.on("-n", "--name MODULE_NAME", "Name of the module. Used to name generated resources") do |name|
|
24
|
+
options[:mod_name] = name
|
25
|
+
end
|
26
|
+
|
27
|
+
opt.on("-c", "--csv FILE", "CSV configuration file input") do |file|
|
28
|
+
options[:csvfile] = file
|
29
|
+
end
|
30
|
+
|
31
|
+
opt.on("-i", "--input DIRECTORY", "Directory for your project's header files") do |dir|
|
32
|
+
options[:hdir] = dir
|
33
|
+
end
|
34
|
+
|
35
|
+
opt.on("-I", "--include DIRECTORY", "Directory for additional header files not part of your project. Example: /usr/include") do |dir|
|
36
|
+
options[:incdir] ||= []
|
37
|
+
options[:incdir] << dir
|
38
|
+
end
|
39
|
+
|
40
|
+
opt.on("-x", "--doxy DIRECTORY", "Directory generated by Doxygen (which include a /xml subdirectory for all XML files") do |dir|
|
41
|
+
options[:xdir] = dir
|
42
|
+
end
|
43
|
+
|
44
|
+
opt.on("-m", "--html", "Instructs Doxygen to also generate HTML documentation for the header files") do
|
45
|
+
options[:html] = true
|
46
|
+
end
|
47
|
+
|
48
|
+
opt.on("-g", "--gen DIRECTORY", "Output directory for Easy-Swig generated .i file(s) aka. 'target'") do |dir|
|
49
|
+
options[:gdir] = dir
|
50
|
+
end
|
51
|
+
|
52
|
+
opt.on("-o", "--output DIRECTORY", "Output directory for SWIG generated files") do |dir|
|
53
|
+
options[:odir] = dir
|
54
|
+
end
|
55
|
+
|
56
|
+
opt.on("-l", "--lang LANGUAGE", "Target language for SWIG") do |lang|
|
57
|
+
options[:lang] = lang
|
58
|
+
end
|
59
|
+
|
60
|
+
opt.on("-t", "--target PATH", "Target .i file as input for SWIG. For directories, SWIG will be invoked once for every .i file") do |path|
|
61
|
+
options[:target] = path
|
62
|
+
end
|
63
|
+
|
64
|
+
opt.on("-u", "--custom FILE", "Custom .i file to be appended at the beginning of the generated .i target. Used for advanced configuration") do |file|
|
65
|
+
options[:custom] = file
|
66
|
+
end
|
67
|
+
|
68
|
+
opt.on("-s", "--no_stl", "Disable support for the C++ Standard Template Library STL") do |file|
|
69
|
+
options[:no_stl] = true
|
70
|
+
end
|
71
|
+
|
72
|
+
opt.on("-h", "--help", "Help") do
|
73
|
+
puts opt_parser
|
74
|
+
end
|
75
|
+
|
76
|
+
opt.separator ""
|
77
|
+
opt.separator "Default option values:"
|
78
|
+
opt.separator ""
|
79
|
+
opt.separator "-d (--default DIRECTORY) Defaults to the current working directory"
|
80
|
+
opt.separator "-n (--name MODULE_NAME) Defaults to the name of the default directory"
|
81
|
+
opt.separator "-c (--csv FILE) Defaults to: path/to/default/dir/api.csv"
|
82
|
+
opt.separator "-i (--input DIRECTORY) Defaults to: path/to/default/dir/include"
|
83
|
+
opt.separator "-I (--include DIRECTORY) Defaults to linux include path: usr/include"
|
84
|
+
opt.separator "-x (--doxy DIRECTORY) Defaults to: path/to/default/dir/easy-swig/doxygen"
|
85
|
+
opt.separator "-m (--html) Defaults to false"
|
86
|
+
opt.separator "-s (--no_stl) Defaults to false"
|
87
|
+
opt.separator "-g (--gen DIRECTORY) Defaults to path/to/default/dir/easy-swig/generate"
|
88
|
+
opt.separator "-o (--output DIRECTORY) Defaults to : path/to/default/dir/easy-swig/swig"
|
89
|
+
opt.separator "-l (--lang LANGUAGE) Defaults to C# (csharp)"
|
90
|
+
opt.separator "-t (--target PATH) Defaults to path/to/default/dir/easy-swig/generate/<MODULE_NAME>.i"
|
91
|
+
opt.separator "-u (--custom FILE) Defaults to path/to/default/dir/custom_config.i"
|
92
|
+
|
93
|
+
end
|
94
|
+
|
95
|
+
opt_parser.parse!
|
96
|
+
|
97
|
+
config = ::EasySwig::Config.new
|
98
|
+
|
99
|
+
if !options[:default].nil? && Dir.exists?(options[:default])
|
100
|
+
puts 'Default directory: ' + options[:default]
|
101
|
+
config.default_dir = options[:default]
|
102
|
+
else
|
103
|
+
puts 'No valid default directory was provided: Use current working directory as default? (y/n)'
|
104
|
+
$stdout.flush
|
105
|
+
answer = $stdin.gets
|
106
|
+
exit! unless answer =~ /^[yY]/
|
107
|
+
end
|
108
|
+
|
109
|
+
config.module_name = options[:mod_name]
|
110
|
+
config.doxy_dir = options[:xdir]
|
111
|
+
config.headers_dir = options[:hdir]
|
112
|
+
config.csv_file = options[:csvfile]
|
113
|
+
config.output_dir = options[:odir]
|
114
|
+
config.generate_dir = options[:gdir]
|
115
|
+
config.html = options[:html]
|
116
|
+
config.lang = options[:lang]
|
117
|
+
config.stl_support = options[:no_stl].nil? ? 'YES' : nil
|
118
|
+
|
119
|
+
options[:custom] ||= "custom_config.i"
|
120
|
+
|
121
|
+
if File.exists?(options[:custom])
|
122
|
+
puts 'Custom configuration file: ' + options[:custom]
|
123
|
+
config.custom_file = options[:custom]
|
124
|
+
else
|
125
|
+
config.custom_file = nil
|
126
|
+
puts 'No custom configuration file found'
|
127
|
+
end
|
128
|
+
|
129
|
+
config.target_file = options[:target]
|
130
|
+
config.includes_dir = options[:incdir]
|
131
|
+
|
132
|
+
config.set_defaults
|
133
|
+
|
134
|
+
case ARGV[0]
|
135
|
+
when "doxygen"
|
136
|
+
EasySwig::doxygen(config)
|
137
|
+
when "generate"
|
138
|
+
EasySwig::generate(config)
|
139
|
+
when "swig"
|
140
|
+
EasySwig::swig(config)
|
141
|
+
else
|
142
|
+
puts opt_parser
|
143
|
+
end
|
data/lib/easy-swig.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require '/home/david/workspace/ruby-doxygen-parser/lib/doxyparser'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'logger'
|
5
|
+
|
6
|
+
require_relative 'config'
|
7
|
+
require_relative 'util/utilities'
|
8
|
+
require_relative 'util/print'
|
9
|
+
require_relative 'util/logger'
|
10
|
+
require_relative 'util/query'
|
11
|
+
require_relative 'generators/properties'
|
12
|
+
require_relative 'generators/generator_util'
|
13
|
+
require_relative 'generators/class_generator'
|
14
|
+
require_relative 'generators/namespace_generator'
|
15
|
+
require_relative 'generators/hfile_generator'
|
16
|
+
require_relative 'generators/generator'
|
17
|
+
require_relative 'features'
|
18
|
+
require_relative 'apinodes/api_node'
|
19
|
+
require_relative 'apinodes/api_namespace'
|
20
|
+
require_relative 'apinodes/api_function'
|
21
|
+
require_relative 'apinodes/api_class'
|
22
|
+
require_relative 'apinodes/api_method'
|
23
|
+
require_relative 'apinodes/api_group'
|
24
|
+
require_relative 'apinodes/inc_file'
|
25
|
+
require_relative 'apinodes/api_variable'
|
26
|
+
require_relative 'apinodes/api_attribute'
|
27
|
+
require_relative 'apinodes/api_enum'
|
28
|
+
|
29
|
+
require_relative 'csharp/generators/csharp_generator'
|
30
|
+
require_relative 'csharp/generators/csharp_namespace_generator'
|
31
|
+
require_relative 'csharp/generators/csharp_class_generator'
|
32
|
+
require_relative 'csharp/csharp_features'
|
33
|
+
|
34
|
+
require_relative 'tasks/swig_task'
|
35
|
+
|
36
|
+
require_relative 'tasks/doxygen_task'
|
37
|
+
require_relative 'readers/csv_parser'
|
38
|
+
require_relative 'tasks/hfiles_manager'
|
39
|
+
require_relative 'tasks/generate_task'
|
40
|
+
|
41
|
+
module EasySwig
|
42
|
+
class << self
|
43
|
+
|
44
|
+
# Parses header files (.h) and generates intermediate XML representation using Doxygen (Doxyparser)
|
45
|
+
# For more information consult Doxyparser documentation {Doxyparser::gen_xml_docs}
|
46
|
+
# @param [Config] config optional configuration for personalized settings. If nothing given, {Config} defaults used
|
47
|
+
def doxygen(config = EasySwig::Config.new)
|
48
|
+
task = DoxygenTask.new(config)
|
49
|
+
task.generate
|
50
|
+
task.dispose
|
51
|
+
end
|
52
|
+
|
53
|
+
# Generates SWIG Interface Files (.i) from Doxygen intermediate XML representation.
|
54
|
+
# This process is configured using a specially crafted CSV file (see documentation),
|
55
|
+
# A subdirectory for every found namespace is created and here are saved the generated .i swig files
|
56
|
+
# @param [Config] config optional configuration for personalized settings. If nothing given, {Config} defaults used
|
57
|
+
def generate(config = EasySwig::Config.new)
|
58
|
+
task = GenerateTask.new(config)
|
59
|
+
task.generate
|
60
|
+
task.dispose
|
61
|
+
end
|
62
|
+
|
63
|
+
# Runs SWIG against the specified target interface files (.i) And generated wrappers in the output directory (see {Config})
|
64
|
+
# @param [Config] config optional configuration for personalized settings. If nothing given, {Config} defaults used
|
65
|
+
def swig(config = EasySwig::Config.new)
|
66
|
+
task = SwigTask.new(config)
|
67
|
+
task.run_swig
|
68
|
+
task.dispose
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/features.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
module EasySwig
|
2
|
+
|
3
|
+
class Features
|
4
|
+
|
5
|
+
def Features.create_instance(lang)
|
6
|
+
ret = case lang
|
7
|
+
when 'java'
|
8
|
+
EasySwig::Java::JavaFeatures.new
|
9
|
+
when 'csharp'
|
10
|
+
EasySwig::Csharp::CsharpFeatures.new
|
11
|
+
else
|
12
|
+
EasySwig::Csharp::CsharpFeatures.new
|
13
|
+
end
|
14
|
+
ret
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
""
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_str
|
26
|
+
to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
def infer_native_name(node)
|
30
|
+
node.basename ||= node.target_name.gsub(".", "::").gsub(/_([a-z])/i) { |match|
|
31
|
+
$1.upcase
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def infer_target_name(node)
|
36
|
+
node.target_name ||= node.basename.gsub("::", ".")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
module EasySwig
|
2
|
+
|
3
|
+
class ClassGenerator
|
4
|
+
include GeneratorUtil
|
5
|
+
|
6
|
+
def initialize(api_cls, all_types, all_innerclasses, all_friends)
|
7
|
+
@api_class = api_cls
|
8
|
+
@all_types = all_types
|
9
|
+
@all_innerclasses = all_innerclasses
|
10
|
+
@all_friends = all_friends
|
11
|
+
@types = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def process_types
|
15
|
+
swig_file = ''
|
16
|
+
swig_file << process_types_for(@api_class)
|
17
|
+
@api_class.api_innerclasses.each { |c|
|
18
|
+
swig_file << process_types_for(c)
|
19
|
+
}
|
20
|
+
swig_file
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_types_for(klass)
|
24
|
+
swig_file = ''
|
25
|
+
klass.parent_types(:all).each { |p_type|
|
26
|
+
begin
|
27
|
+
process_type(p_type, klass)
|
28
|
+
rescue ArgumentError; end
|
29
|
+
}
|
30
|
+
remove_methods = []
|
31
|
+
klass.api_methods.each { |m|
|
32
|
+
begin
|
33
|
+
process_type(m.type, klass) unless m.constructor? || m.destructor?
|
34
|
+
m.params.each { |p|
|
35
|
+
process_type(p.type, klass)
|
36
|
+
}
|
37
|
+
rescue ArgumentError
|
38
|
+
remove_methods << m
|
39
|
+
swig_file << %Q{%rename("$ignore") #{klass.name}::#{m.basename};} + "\n"
|
40
|
+
end
|
41
|
+
}
|
42
|
+
klass.api_methods.reject! { |m| remove_methods.include?(m) }
|
43
|
+
|
44
|
+
remove_attributes = []
|
45
|
+
klass.api_attributes.each { |a|
|
46
|
+
begin
|
47
|
+
process_type(a.type, klass)
|
48
|
+
rescue ArgumentError
|
49
|
+
remove_attributes << a
|
50
|
+
swig_file << %Q{%rename("$ignore") #{klass.name}::#{a.basename};} + "\n"
|
51
|
+
end
|
52
|
+
}
|
53
|
+
klass.api_attributes.reject! { |a| remove_attributes.include?(a) }
|
54
|
+
swig_file
|
55
|
+
end
|
56
|
+
|
57
|
+
def gen_methods
|
58
|
+
swig_file = ''
|
59
|
+
@api_class.ignored_methods.each { |m|
|
60
|
+
swig_file << %Q{%rename("$ignore") #{@api_class.name}::#{m.basename};} + "\n"
|
61
|
+
}
|
62
|
+
properties = {}
|
63
|
+
@api_class.api_methods.each { |m|
|
64
|
+
if m.basename=='getTextureAddressingMode'
|
65
|
+
puts "Aqui"
|
66
|
+
end
|
67
|
+
features = m.features
|
68
|
+
if features.properties
|
69
|
+
getter = m.getter_for
|
70
|
+
setter = m.setter_for
|
71
|
+
if setter
|
72
|
+
properties[m.target_name] ||= EasySwig::Properties.new
|
73
|
+
properties[m.target_name].setter = m.basename
|
74
|
+
properties[m.target_name].static = m.static
|
75
|
+
properties[m.target_name].type_setter ||= m.params[0].type
|
76
|
+
elsif getter
|
77
|
+
properties[m.target_name] ||= EasySwig::Properties.new
|
78
|
+
properties[m.target_name].getter = m.basename
|
79
|
+
properties[m.target_name].static = m.static
|
80
|
+
properties[m.target_name].type_getter = m.type
|
81
|
+
else
|
82
|
+
swig_file << %Q{%rename(#{m.target_name}) #{m.name};\n} unless is_operator?(m.basename) || @api_class.is_enum_or_innerclass?(m.target_name)
|
83
|
+
next
|
84
|
+
end
|
85
|
+
properties[m.target_name].class_name = @api_class.name
|
86
|
+
else
|
87
|
+
swig_file << %Q{%rename(#{m.target_name}) #{m.name};\n} unless is_operator?(m.basename) || @api_class.is_enum_or_innerclass?(m.target_name)
|
88
|
+
end
|
89
|
+
}
|
90
|
+
properties.each { |attribute, property|
|
91
|
+
next if property.getter.nil?
|
92
|
+
next if property.type_setter != property.type_getter
|
93
|
+
type = property.type_getter
|
94
|
+
case get_reference_type(type, @api_class)
|
95
|
+
when :ptr
|
96
|
+
macro = 'attribute'
|
97
|
+
escaped_typename = type.escaped_name.gsub('>::type', '>') # TODO only for Ogre
|
98
|
+
when :ref
|
99
|
+
macro = 'attribute2'
|
100
|
+
next # Ref Properties not supported
|
101
|
+
when :str
|
102
|
+
macro = 'attributestring'
|
103
|
+
escaped_typename = type.escaped_name
|
104
|
+
when :prim_ptr
|
105
|
+
macro = 'attribute'
|
106
|
+
escaped_typename = type.name
|
107
|
+
when :val
|
108
|
+
macro = 'attributeval'
|
109
|
+
next # Properties per Value not supported
|
110
|
+
end
|
111
|
+
unless macro.nil?
|
112
|
+
macro << '_static' if property.static
|
113
|
+
swig_file << "%#{macro}(#{property.class_name}, #{escaped_typename}, #{attribute}, #{property.getter}, #{property.setter});\n"
|
114
|
+
end
|
115
|
+
}
|
116
|
+
swig_file
|
117
|
+
end
|
118
|
+
|
119
|
+
def gen_attributes
|
120
|
+
swig_file = ''
|
121
|
+
@api_class.ignored_attributes.each { |m|
|
122
|
+
swig_file << %Q{%rename("$ignore") #{m.name};} + "\n"
|
123
|
+
}
|
124
|
+
@api_class.api_attributes.each { |a|
|
125
|
+
swig_file << %Q{%rename(#{a.target_name}) #{a.name};} + "\n"
|
126
|
+
}
|
127
|
+
swig_file
|
128
|
+
end
|
129
|
+
|
130
|
+
def gen_enums
|
131
|
+
swig_file = ''
|
132
|
+
@api_class.ignored_enums.each { |m|
|
133
|
+
swig_file << %Q{%rename("$ignore") #{m.name};} + "\n"
|
134
|
+
}
|
135
|
+
@api_class.api_enums.each { |enum|
|
136
|
+
if anonymous_enum?(enum) # @Anonymous Enums
|
137
|
+
swig_file << "\nnamespace #{@api_class.parent.name} {"
|
138
|
+
swig_file << enum_snippet(enum)
|
139
|
+
swig_file << "\t}\n"
|
140
|
+
swig_file << ignore_enum_values_snippet(enum)
|
141
|
+
else
|
142
|
+
swig_file << %Q{%rename(#{enum.target_name}) #{enum.name};} + "\n"
|
143
|
+
end
|
144
|
+
}
|
145
|
+
swig_file
|
146
|
+
end
|
147
|
+
|
148
|
+
def gen_innerclasses
|
149
|
+
swig_file = ''
|
150
|
+
@api_class.ignored_innerclasses.each { |c|
|
151
|
+
swig_file << %Q{%rename("$ignore") #{@api_class.name}::#{c.basename};} + "\n"
|
152
|
+
}
|
153
|
+
@api_class.api_innerclasses.each { |c|
|
154
|
+
if c.nested_support # Innerclasses
|
155
|
+
swig_file << nested_workaround(c)
|
156
|
+
else
|
157
|
+
swig_file << %Q{%rename(#{c.target_name}) #{@api_class.name}::#{c.basename};\n}
|
158
|
+
end
|
159
|
+
}
|
160
|
+
swig_file
|
161
|
+
end
|
162
|
+
|
163
|
+
def gen_parent_templates
|
164
|
+
swig_file = "\n"
|
165
|
+
@types.invert.each { |expanded, typename|
|
166
|
+
swig_file << template_snippet(typename, expanded)
|
167
|
+
}
|
168
|
+
swig_file
|
169
|
+
end
|
170
|
+
|
171
|
+
def gen_type_templates
|
172
|
+
swig_file = "\n"
|
173
|
+
@types.invert.each { |expanded, typename|
|
174
|
+
swig_file << template_snippet(typename, expanded)
|
175
|
+
}
|
176
|
+
swig_file
|
177
|
+
end
|
178
|
+
|
179
|
+
def gen_friends
|
180
|
+
swig_file = ''
|
181
|
+
if @api_class.friend_support
|
182
|
+
namespace = @api_class.parent
|
183
|
+
friend_functions = @api_class.friends.delete_if{ |f| f.is_class? || f.is_qualified? }
|
184
|
+
return '' if friend_functions.empty?
|
185
|
+
|
186
|
+
swig_file << "namespace #{namespace.name} {\n"
|
187
|
+
swig_file << "\tclass #{@api_class.basename};\n"
|
188
|
+
friend_functions.each { |f|
|
189
|
+
next if @all_friends[f.basename + f.args]
|
190
|
+
swig_file << "\t#{f.type.name} #{name_for_friend(f.basename, f.params.size)}#{f.args};\n"
|
191
|
+
}
|
192
|
+
swig_file << "}\n"
|
193
|
+
swig_file << "%{\nnamespace #{namespace.name} {\n"
|
194
|
+
swig_file << "\tclass #{@api_class.basename};\n"
|
195
|
+
friend_functions.each { |f|
|
196
|
+
signature = f.basename + f.args
|
197
|
+
next if @all_friends[signature]
|
198
|
+
@all_friends[signature] = 1
|
199
|
+
param_names = f.params.map { |p| p.declname }.join(', ') # TODO What happens when declname is empty
|
200
|
+
friend_name = name_for_friend(f.basename, f.params.size)
|
201
|
+
swig_file << "\t#{f.type.name} #{friend_name}#{f.args}{\n"
|
202
|
+
swig_file << "\t\treturn #{f.basename}(#{param_names});\n\t}\n"
|
203
|
+
}
|
204
|
+
swig_file << "}\n%}\n"
|
205
|
+
end
|
206
|
+
swig_file
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|