2009年4月30日木曜日

DLLからDEFファイルを作る

DLLファイルからDEFファイルを自動生成する必要があって、MinGWのpexportsを持っていなかったので、さくっと書いてみた。

dll_to_def.rb
#!ruby -Ku
# Generate the .def file from .dll using 'dumpbin.exe'
# 2009-04-30 23:43:20

class ExportsList
FUNCTION_LINE_PATTERN = /^\s+(\d+)\s+[0-9A-Fa-f]+\s+[0-9A-Fa-f]+\s+(.*)$/

def initialize(dllname)
@dllname = dllname
@max_name_length = 0
@exports = []
dumpbin(dllname) do |line|
next unless line =~ FUNCTION_LINE_PATTERN
@exports << [$1, $2]
@max_name_length = $2.length if @max_name_length < $2.length
end
end

def save_as_def
width = ((@max_name_length + 7) / 8) * 8
basename = File.basename(@dllname, '.dll')
File.open(basename + '.def', 'w') do |f|
f.puts(%Q|LIBRARY "#{basename}"|)
f.puts
f.puts('EXPORTS')
@exports.each do |i, name|
f.print("\t#{name}")
f.print("\t" * ((width + 7 - name.length) / 8))
f.puts("@#{i}")
end
end
end

private
def dumpbin(dllname)
raise "Command not found: dumpbin" unless cmd_exist?('dumpbin')
Kernel.open("|dumpbin /exports #{dllname}") do |f|
while line = f.gets
yield(line)
end
end
end

def cmd_exist?(cmd)
ENV['PATH'].split(';').each do |path|
(';' + ENV['PATHEXT']).split(';').each do |ext|
pathname = File.join(File.expand_path(path), cmd + ext)
return true if File.exist?(pathname)
end
end
nil
end
end

if $0 == __FILE__
ARGV.each do |dllname|
ExportsList.new(dllname).save_as_def
end
end

0 件のコメント:

コメントを投稿