diff --git a/MyClientCpp/Main.cpp b/MyClientCpp/Main.cpp index 817bef2..b13a7a7 100644 --- a/MyClientCpp/Main.cpp +++ b/MyClientCpp/Main.cpp @@ -82,7 +82,16 @@ int main() { try { auto cruncher = server->GetNumberCruncher(); - double pi = cruncher->ComputePi(); + // try to cast to INumberCruncher2 to check if the new interface is implemented + MyInterfaces::INumberCruncher2Ptr cruncher2 = cruncher; + double pi = 0; + if (cruncher2) { + // use new interface + pi = cruncher2->ComputePi2(); + } else { + // fallback to old interface + pi = cruncher->ComputePi(); + } std::wcout << L"pi = " << pi << std::endl; auto callback = CreateLocalInstance(); diff --git a/MyClientCs/Program.cs b/MyClientCs/Program.cs index 9ddfc3e..21c4b3e 100644 --- a/MyClientCs/Program.cs +++ b/MyClientCs/Program.cs @@ -13,7 +13,16 @@ static void CommunicateWithServer() { var cruncher = server.GetNumberCruncher(); - double pi = cruncher.ComputePi(); + double pi = 0; + try { + // try to cast to INumberCruncher2 to check if the new interface is implemented + var cruncher2 = (MyInterfaces.INumberCruncher2)cruncher; + // use new interface + pi = cruncher2.ComputePi2(); + } catch (System.InvalidCastException) { + // fallback to old interface + pi = cruncher.ComputePi(); + } Console.WriteLine($"pi = {pi}"); // release reference to help GC clean up (not strctly needed) diff --git a/MyExeServerCpp/MyServerImpl.hpp b/MyExeServerCpp/MyServerImpl.hpp index 012f19e..99d5bab 100644 --- a/MyExeServerCpp/MyServerImpl.hpp +++ b/MyExeServerCpp/MyServerImpl.hpp @@ -18,7 +18,8 @@ using namespace MyInterfaces; class ATL_NO_VTABLE NumberCruncher : public CComObjectRootEx, // also compatible with STA public CComCoClass, // no CLSID needed - public INumberCruncher + public INumberCruncher, + public INumberCruncher2 { public: NumberCruncher() { @@ -33,12 +34,21 @@ class ATL_NO_VTABLE NumberCruncher : if (!val) return E_INVALIDARG; + *val = M_PI + 0.01; // old inaccurate impl. + return S_OK; + } + + HRESULT STDMETHODCALLTYPE raw_ComputePi2(/*out*/double* val) override { + if (!val) + return E_INVALIDARG; + *val = M_PI; return S_OK; } BEGIN_COM_MAP(NumberCruncher) COM_INTERFACE_ENTRY(INumberCruncher) + COM_INTERFACE_ENTRY(INumberCruncher2) END_COM_MAP() }; diff --git a/MyExeServerCs/MyServerImpl.cs b/MyExeServerCs/MyServerImpl.cs index 5688bf4..195315d 100644 --- a/MyExeServerCs/MyServerImpl.cs +++ b/MyExeServerCs/MyServerImpl.cs @@ -126,7 +126,7 @@ public void Unsubscribe(IMyClient client) } /** Non-creatable COM class that doesn't need any CLSID. */ - public sealed class NumberCruncher : ComSupport.ComClass, MyInterfaces.INumberCruncher + public sealed class NumberCruncher : ComSupport.ComClass, MyInterfaces.INumberCruncher, MyInterfaces.INumberCruncher2 { public NumberCruncher() { @@ -139,6 +139,11 @@ public NumberCruncher() } public double ComputePi () + { + return Math.PI + 0.01; // old inaccurate impl. + } + + public double ComputePi2() { return Math.PI; } diff --git a/MyInterfaces/MyInterfaces.idl b/MyInterfaces/MyInterfaces.idl index 029cae2..74f0de3 100644 --- a/MyInterfaces/MyInterfaces.idl +++ b/MyInterfaces/MyInterfaces.idl @@ -90,6 +90,15 @@ interface INumberCruncher : IUnknown { HRESULT ComputePi([out, retval] double *ret); }; +[object, +oleautomation, +uuid(E847D928-753B-45AC-A795-8716D87FABB0), +helpstring("New and better number crunching interface")] +interface INumberCruncher2 : IUnknown { + [helpstring("Test method")] + HRESULT ComputePi2([out, retval] double* ret); +}; + [object, oleautomation, uuid(F586D6F4-AF37-441E-80A6-3D33D977882D), @@ -107,6 +116,8 @@ interface IMyServer : IUnknown { [uuid(46F3FEB2-121D-4830-AA22-0CDA9EA90DC3)] library MyInterfaces { + interface INumberCruncher2; + [uuid(AF080472-F173-4D9D-8BE7-435776617347)] coclass MyServer { [default] interface IMyServer; diff --git a/UNREGISTER.bat b/UNREGISTER.bat index 3794efd..26fa481 100644 --- a/UNREGISTER.bat +++ b/UNREGISTER.bat @@ -10,6 +10,7 @@ for %%P in (32 64) do ( reg delete "HKCR\Interface\{BE3FF6C1-94F5-4974-913C-237C9AB29679}" /f /reg:%%P 2> NUL reg delete "HKCR\Interface\{F586D6F4-AF37-441E-80A6-3D33D977882D}" /f /reg:%%P 2> NUL reg delete "HKCR\Interface\{B5506675-17E0-4709-A31A-305E36D0E2FA}" /f /reg:%%P 2> NUL + reg delete "HKCR\Interface\{E847D928-753B-45AC-A795-8716D87FABB0}" /f /reg:%%P 2> NUL ) :: Delete MyInterfaces TypeLib