Po wcześniej przytoczonej teorii (COM , DCOM , .NET , Marshalling , .NET i COM) chyba każdy już wie od czego zacząć, by napisać klienta OPC w C#. Niestety nie obędzie się tutaj bez znajomości specyfikacji. Dodatkowo potrzebne będzie spore doświadczenie w korzystaniu z .NET Platform Invocation Services (czyli m.in marshalling'u i umiejętność konwersji definicji wywołań bibliotek kodu niezarządzalnego na definicję języka C#).
Spójrzmy na definicję przykładowej metody AddItems (z interfejsu OPC Item Management: "IOPCItemMgt"):
HRESULT AddItems( [in] DWORD dwCount, [in, size_is( dwCount)] OPCITEMDEF * pItemArray, [out, size_is(,dwCount)] OPCITEMRESULT ** ppAddResults, [out, size_is(,dwCount)] HRESULT ** ppErrors );
Ta definicja napisana w C# będzie wyglądała następująco:
int AddItems( [In] int dwCount, [In] IntPtr pItemArray, [Out] out IntPtr ppAddResults, [Out] out IntPtr ppErrors );
Oczywiście postępując w ten sposób i deklarując parametry jako IntPtr, tracimy wiele informacji. Kolejna sprawa, to standardowe mapowanie błędów zwracanych przez obiekt COM (jako HRESULT), które są konwertowane przez mechanizm marszalingu .NET (.NET marshaller) na wyjątek: COMException
. Dodatkowo niektóre metody dostępne poprzez COM zwracają kody wyników: zwykle S_OK (ale czasami inne, np. S_FALSE). Z domyślnym mapowaniem, ta informacja może zostać zagubiona. Aby ominąć te problemy można zadeklarować funkcję interfejsu korzystając ze specjalnego atrybutu PreserveSig . Spójrzcie na kod poniżej:
[ComVisible(true), ComImport, Guid("39c13a54-011e-11d0-9675-0020afd8adb3"), InterfaceType( ComInterfaceType.InterfaceIsIUnknown )] internal interface IOPCItemMgt { [PreserveSig] int AddItems( [In] int dwCount, [In] IntPtr pItemArray, [Out] out IntPtr ppAddResults, [Out] out IntPtr ppErrors ); ...
W tej części będzie to już wszystko. Dla tych, którzy chcą rozszerzyć opisane tutaj zagadnienia, polecam artykuł: http://www.codeproject.com/KB/COM/opcdotnet.aspx
Warto też przeczytać: OPC Client .NET (w języku C# (csharp))
OdpowiedzUsuńzezarte z codeproject
OdpowiedzUsuńNiniejszy wpis jest częścią większego artykułu: "OPC, DCOM, .NET i C# w jednym stali domu", który powstał na bazie różnych źródeł, jak i mojej wiedzy i doświadczeń.
OdpowiedzUsuńW tym wpisie inspirowałem się artykułem "OPC and .NET with COM Interoperability" z Codeproject, czego nie ukrywałem odsyłając na końcu wpisu do wspomnianego artykułu.
Jestem pod wrażeniem tego jak doskonale przekazujesz swoją wiedzę.
OdpowiedzUsuń