module WindowsCOM::COMCallback

Public Class Methods

[](iface) click to toggle source
# File lib/windows_com/common.rb, line 241
def self.[](iface)
        Class.new(iface) {
                def initialize
                        @vtbl = self.class::Vtbl.new
                        @vtbl.members.each { |name|
                                params, ret = @vtbl.class::Spec[name]
                                ffi_params = [:pointer, *params] # prepend *this* ptr to FFI func signature

                                @vtbl[name] = instance_variable_set("@__ffi_func__#{name}",
                                        FFI::Function.new(ret, ffi_params, convention: :stdcall) { |*args|
                                                args.shift # remove *this* ptr for Ruby meth call

                                                STDERR.puts [:rb_call, self.class, name, args].inspect if
                                                        WINDOWS_COM_TRACE_CALL_ARGS

                                                __send__(name, *args)
                                        }
                                )
                        }

                        @vptr = WindowsCOM::COMVptr_.new
                        @vptr[:lpVtbl] = @vtbl

                        @refc = 0
                        AddRef()
                end

                attr_reader :refc

                def QueryInterface(iid, ppv)
                        unless self.class::IID == iid || WindowsCOM::IUnknown::IID == iid
                                STDERR.puts "#{self}.#{__method__} called with unsupported interface id (IID: #{iid})" if $DEBUG

                                ppv.write_pointer(0)
                                return WindowsCOM::E_NOINTERFACE
                        end

                        ppv.write_pointer(@vptr)
                        AddRef()
                        WindowsCOM::S_OK
                end

                def AddRef
                        @refc += 1

                        STDERR.puts "#{self}.#{__method__} (@refc: #{@refc})" if
                                $DEBUG || WINDOWS_COM_TRACE_CALLBACK_REFCOUNT

                        @refc
                end

                def Release
                        @refc -= 1

                        STDERR.puts "#{self}.#{__method__} (@refc: #{@refc})" if
                                $DEBUG || WINDOWS_COM_TRACE_CALLBACK_REFCOUNT

                        if @refc == 0
                                @vtbl.pointer.free
                                @vptr.pointer.free

                                STDERR.puts "#{self}.@#{@vtbl} freed\n#{self}.@#{@vptr} freed" if
                                        $DEBUG || WINDOWS_COM_TRACE_CALLBACK_REFCOUNT
                        end

                        @refc
                end

                (self::Vtbl.members - WindowsCOM::IUnknown::Vtbl.members).each { |name|
                        define_method(name) { |*args|
                                WindowsCOM::E_NOTIMPL
                        }
                }
        }
end
new() click to toggle source
# File lib/windows_com/common.rb, line 243
def initialize
        @vtbl = self.class::Vtbl.new
        @vtbl.members.each { |name|
                params, ret = @vtbl.class::Spec[name]
                ffi_params = [:pointer, *params] # prepend *this* ptr to FFI func signature

                @vtbl[name] = instance_variable_set("@__ffi_func__#{name}",
                        FFI::Function.new(ret, ffi_params, convention: :stdcall) { |*args|
                                args.shift # remove *this* ptr for Ruby meth call

                                STDERR.puts [:rb_call, self.class, name, args].inspect if
                                        WINDOWS_COM_TRACE_CALL_ARGS

                                __send__(name, *args)
                        }
                )
        }

        @vptr = WindowsCOM::COMVptr_.new
        @vptr[:lpVtbl] = @vtbl

        @refc = 0
        AddRef()
end

Public Instance Methods

AddRef() click to toggle source
# File lib/windows_com/common.rb, line 283
def AddRef
        @refc += 1

        STDERR.puts "#{self}.#{__method__} (@refc: #{@refc})" if
                $DEBUG || WINDOWS_COM_TRACE_CALLBACK_REFCOUNT

        @refc
end
QueryInterface(iid, ppv) click to toggle source
# File lib/windows_com/common.rb, line 270
def QueryInterface(iid, ppv)
        unless self.class::IID == iid || WindowsCOM::IUnknown::IID == iid
                STDERR.puts "#{self}.#{__method__} called with unsupported interface id (IID: #{iid})" if $DEBUG

                ppv.write_pointer(0)
                return WindowsCOM::E_NOINTERFACE
        end

        ppv.write_pointer(@vptr)
        AddRef()
        WindowsCOM::S_OK
end
Release() click to toggle source
# File lib/windows_com/common.rb, line 292
def Release
        @refc -= 1

        STDERR.puts "#{self}.#{__method__} (@refc: #{@refc})" if
                $DEBUG || WINDOWS_COM_TRACE_CALLBACK_REFCOUNT

        if @refc == 0
                @vtbl.pointer.free
                @vptr.pointer.free

                STDERR.puts "#{self}.@#{@vtbl} freed\n#{self}.@#{@vptr} freed" if
                        $DEBUG || WINDOWS_COM_TRACE_CALLBACK_REFCOUNT
        end

        @refc
end