ruby-changes:6331
From: suke <ko1@a...>
Date: Thu, 3 Jul 2008 19:31:15 +0900 (JST)
Subject: [ruby-changes:6331] Ruby:r17847 (ruby_1_8): * ext/win32ole/win32ole.c: avoid creating Ruby object during
suke 2008-07-03 19:30:42 +0900 (Thu, 03 Jul 2008) New Revision: 17847 Removed files: branches/ruby_1_8/ext/win32ole/tests/testOLEEVENT.rb Modified files: branches/ruby_1_8/ChangeLog branches/ruby_1_8/ext/win32ole/tests/testWIN32OLE.rb branches/ruby_1_8/ext/win32ole/tests/testall.rb branches/ruby_1_8/ext/win32ole/win32ole.c Log: * ext/win32ole/win32ole.c: avoid creating Ruby object during GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313] * ext/win32ole/tests: add test_win32ole_event.rb, remove testOLEEVENT.rb http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=17847 Index: ruby_1_8/ext/win32ole/tests/testOLEEVENT.rb =================================================================== --- ruby_1_8/ext/win32ole/tests/testOLEEVENT.rb (revision 17846) +++ ruby_1_8/ext/win32ole/tests/testOLEEVENT.rb (revision 17847) @@ -1,91 +0,0 @@ -require 'rubyunit' -require 'win32ole' - -class TestWIN32OLE_EVENT < RUNIT::TestCase - def setup - @excel = WIN32OLE.new("Excel.Application") - @excel.visible = true - @event = "" - @event2 = "" - end - def test_on_event - book = @excel.workbooks.Add - value = "" - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event('SheetChange'){|arg1, arg2| - begin - value = arg1.value - rescue - value = $!.message - end - } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("OK", value) - end - - def handler1 - @event += "handler1" - end - def handler2 - @event += "handler2" - end - - def handler3 - @event += "handler3" - end - - def test_on_event2 - book = @excel.workbooks.Add - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event('SheetChange'){|arg1, arg2| - handler1 - } - ev.on_event('SheetChange'){|arg1, arg2| - handler2 - } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("handler2", @event) - end - - def test_on_event3 - book = @excel.workbooks.Add - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event{ handler1 } - ev.on_event{ handler2 } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("handler2", @event) - end - - def test_on_event4 - book = @excel.workbooks.Add - begin - ev = WIN32OLE_EVENT.new(book, 'WorkbookEvents') - ev.on_event{ handler1 } - ev.on_event{ handler2 } - ev.on_event('SheetChange'){|arg1, arg2| handler3 } - book.Worksheets(1).Range("A1").value = "OK" - ensure - book.saved = true - end - assert_equal("handler3", @event) - end - - def teardown - @excel.quit - @excel = nil - GC.start - end -end - Index: ruby_1_8/ext/win32ole/tests/testWIN32OLE.rb =================================================================== --- ruby_1_8/ext/win32ole/tests/testWIN32OLE.rb (revision 17846) +++ ruby_1_8/ext/win32ole/tests/testWIN32OLE.rb (revision 17847) @@ -156,7 +156,8 @@ sheet.range("A3").value = "=A1*10 + 9" assert_equal(9999999999, sheet.range("A2").value) assert_equal(9999999999, sheet.range("A3").value) - + sheet.range("A4").value = "2008/03/04" + assert_equal("2008/03/04 00:00:00", sheet.range("A4").value) ensure book.saved = true end Index: ruby_1_8/ext/win32ole/tests/testall.rb =================================================================== --- ruby_1_8/ext/win32ole/tests/testall.rb (revision 17846) +++ ruby_1_8/ext/win32ole/tests/testall.rb (revision 17847) @@ -12,4 +12,5 @@ require "test_ole_methods.rb" require "test_propertyputref.rb" require "test_word.rb" +require "test_win32ole_event.rb" # require "testOLEEVENT" Index: ruby_1_8/ext/win32ole/win32ole.c =================================================================== --- ruby_1_8/ext/win32ole/win32ole.c (revision 17846) +++ ruby_1_8/ext/win32ole/win32ole.c (revision 17847) @@ -29,8 +29,8 @@ #include <varargs.h> #define va_init_list(a,b) va_start(a) #endif +#include <objidl.h> - #define DOUT fprintf(stderr,"[%d]\n",__LINE__) #define DOUTS(x) fprintf(stderr,"[%d]:" #x "=%s\n",__LINE__,x) #define DOUTMSG(x) fprintf(stderr, "[%d]:" #x "\n",__LINE__) @@ -79,7 +79,7 @@ #define WC2VSTR(x) ole_wc2vstr((x), TRUE) -#define WIN32OLE_VERSION "0.7.5" +#define WIN32OLE_VERSION "0.7.6" typedef HRESULT (STDAPICALLTYPE FNCOCREATEINSTANCEEX) (REFCLSID, IUnknown*, DWORD, COSERVERINFO*, DWORD, MULTI_QI*); @@ -157,6 +157,9 @@ static IDispatchVtbl com_vtbl; static UINT cWIN32OLE_cp = CP_ACP; static VARTYPE g_nil_to = VT_ERROR; +static IMessageFilterVtbl message_filter; +static IMessageFilter imessage_filter = { &message_filter }; +static IMessageFilter* previous_filter; struct oledata { IDispatch *pDispatch; @@ -203,6 +206,101 @@ static VALUE ole_variant2val(VARIANT*); static void ole_val2variant(VALUE, VARIANT*); +static HRESULT (STDMETHODCALLTYPE mf_QueryInterface)( + IMessageFilter __RPC_FAR * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject) +{ + if (MEMCMP(riid, &IID_IUnknown, GUID, 1) == 0 + || MEMCMP(riid, &IID_IMessageFilter, GUID, 1) == 0) + { + *ppvObject = &message_filter; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG (STDMETHODCALLTYPE mf_AddRef)( + IMessageFilter __RPC_FAR * This) +{ + return 1; +} + +static ULONG (STDMETHODCALLTYPE mf_Release)( + IMessageFilter __RPC_FAR * This) +{ + return 1; +} + +static DWORD (STDMETHODCALLTYPE mf_HandleInComingCall)( + IMessageFilter __RPC_FAR * pThis, + DWORD dwCallType, //Type of incoming call + HTASK threadIDCaller, //Task handle calling this task + DWORD dwTickCount, //Elapsed tick count + LPINTERFACEINFO lpInterfaceInfo //Pointer to INTERFACEINFO structure + ) +{ +#ifdef DEBUG_MESSAGEFILTER + printf("incoming %08X, %08X, %d\n", dwCallType, threadIDCaller, dwTickCount); + fflush(stdout); +#endif + switch (dwCallType) + { + case CALLTYPE_ASYNC: + case CALLTYPE_TOPLEVEL_CALLPENDING: + case CALLTYPE_ASYNC_CALLPENDING: + if (rb_during_gc()) { + return SERVERCALL_RETRYLATER; + } + break; + default: + break; + } + if (previous_filter) { + return previous_filter->lpVtbl->HandleInComingCall(previous_filter, + dwCallType, + threadIDCaller, + dwTickCount, + lpInterfaceInfo); + } + return SERVERCALL_ISHANDLED; +} + +static DWORD (STDMETHODCALLTYPE mf_RetryRejectedCall)( + IMessageFilter* pThis, + HTASK threadIDCallee, //Server task handle + DWORD dwTickCount, //Elapsed tick count + DWORD dwRejectType //Returned rejection message + ) +{ + if (previous_filter) { + return previous_filter->lpVtbl->RetryRejectedCall(previous_filter, + threadIDCallee, + dwTickCount, + dwRejectType); + } + return 1000; +} + +static DWORD (STDMETHODCALLTYPE mf_MessagePending)( + IMessageFilter* pThis, + HTASK threadIDCallee, //Called applications task handle + DWORD dwTickCount, //Elapsed tick count + DWORD dwPendingType //Call type + ) +{ + if (rb_during_gc()) { + return PENDINGMSG_WAITNOPROCESS; + } + if (previous_filter) { + return previous_filter->lpVtbl->MessagePending(previous_filter, + threadIDCallee, + dwTickCount, + dwPendingType); + } + return PENDINGMSG_WAITNOPROCESS; +} + typedef struct _Win32OLEIDispatch { IDispatch dispatch; @@ -625,6 +723,11 @@ /* atexit((void (*)(void))ole_uninitialize); */ + hr = CoRegisterMessageFilter(&imessage_filter, &previous_filter); + if(FAILED(hr)) { + previous_filter = NULL; + ole_raise(hr, rb_eRuntimeError, "fail: install OLE MessageFilter"); + } } } @@ -6183,6 +6286,14 @@ com_vtbl.GetTypeInfo = GetTypeInfo; com_vtbl.GetIDsOfNames = GetIDsOfNames; com_vtbl.Invoke = Invoke; + + message_filter.QueryInterface = mf_QueryInterface; + message_filter.AddRef = mf_AddRef; + message_filter.Release = mf_Release; + message_filter.HandleInComingCall = mf_HandleInComingCall; + message_filter.RetryRejectedCall = mf_RetryRejectedCall; + message_filter.MessagePending = mf_MessagePending; + com_hash = Data_Wrap_Struct(rb_cData, rb_mark_hash, st_free_table, st_init_numtable()); cWIN32OLE = rb_define_class("WIN32OLE", rb_cObject); Index: ruby_1_8/ChangeLog =================================================================== --- ruby_1_8/ChangeLog (revision 17846) +++ ruby_1_8/ChangeLog (revision 17847) @@ -1,3 +1,14 @@ +Thu Jul 3 19:23:20 2008 Masaki Suketa <masaki.suketa@n...> + + * ext/win32ole/win32ole.c: avoid creating Ruby object during + GC. thanks to arton <artonx AT yahoo.co.jp>. [ruby-dev:35313] + + * ext/win32ole/tests: add test_win32ole_event.rb, remove + testOLEEVENT.rb + + * ext/win32ole/tests/testWIN32OLE.rb(test_convert_bignum): + fix test. + Thu Jul 3 16:46:56 2008 Tanaka Akira <akr@f...> * include/ruby/ruby.h (POSFIXABLE): use FIXNUM_MAX+1 instead of -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/