easy-swig 1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|