240 likes | 265 Views
Explore the realm of Native/Managed Interop in .NET programming, including Platform Invoke Services, Mixed Mode Programming, COM Interoperability, and Java Native Interop. Learn about PInvoke, DllImportAttribute, and BindingFlags in C# and C++. Dive into COM Tools, Runtime-Callable Wrappers, Proxies, and Runtime Management. Understand the significance of Primary Interop Assemblies (PIA) in achieving seamless communication between different types. Discover the power of Interop Marshaling and its impact on data conversion between COM components and .NET types for efficient cross-platform integration.
E N D
Native / Managed Interop Jim Fawcett CSE775 – Distributed Objects Spring 2012
References • .Net and COM, the Complete Interoperability Guide, Adam Nathan, SAMS, 2002 • The title is accurate
Interop • Interop happens in four ways: • Platform Invoke Services (Pinvoke) • Mixed mode programmin with C++/CLR • COM Interoperability • Java / Native Interop (JNI)
Platform Invocation Services • The Win32 API and other programs expose static entry points in libraries: • Kernel32.dll, user32.dll, gdi32.dll, and advapi32.dll • User defined DLLs • PInvoke supports • Calling entry points in unmanaged dlls with LoadLibrary and GetProcAddress • Passing function pointers to unmanaged code for callbacks
InteropServices • DllImportAttribute • One required string parameter holds name of the DLL containing entry point • Optional CallingConvention • Optional CharSet • Optional EntryPoint if different from managed method • Optional ExactSpelling for W or A • Optional PreserveSig • Optional SetLastError
CallingConvention Enum Cdecl used for methods with variable number of parameters FastCall not used StdCall is default ThisCall used to call class methods CharSet Enum Ansi for 8 bit chars Auto uses the OS type Unicode for 16 bit chars C# and C++ default to Ansi DllImportAttribute Arguments
Mixed Mode Programming with C++ • Managed and unmanaged class instances can directly call each other’s functions • Managed code can hold references to unmanaged class instances and vice versa • See ManagedCpp folder for examples
COM Interop • COM Interop is made up of three parts: • Core services • Interop APIs in System.Runtime.InteropServices • Tool support
Example: Using Speech API using System; using System.Collections.Generic; using System.Text; using SpeechLib; namespace SpeakToMe { class hello { static void Main(string[] args) { SpVoice voice = new SpVoice(); voice.Speak( "Hello CSE775 - Distributed Objects", SpeechVoiceSpeakFlags.SVSFDefault ); } } } • Navigate to: • C:\program files\common files\Microsoft shared\speech • tlbimp sapi.dll-->SpeechLib.dll
COM Tools OleView displays type libraries MIDL compiles IDL into COM source code and type libraries Regsvr32 registers and unregisters COM components RegEdit32 edits Windows registry .Net Tools TlbImp creates an interop assembly from a COM type library TlbExp creates a type library from a .Net assembly Regasm registers and unregisters assemblies AxImp converts an ActiveX type library to an interop assembly and an activeX assembly Regsvcs installs and uninstalls assemblies in COM+ catalog Tool Support
Callable Wrappers • Runtime-callable and COM-callable wrappers • They handle: • Data marshaling • Exception handling • Object lifetime
Runtime-Callable Wrappers • Runtime Callable Wrapper (RCW) • A .Net class that is a COM client, using IUnknown and IDispatch. • You could hand craft an RCW using managed C++, which can directly call the COM API. • However, you don’t need to. Just use tlbimp.exe
COM-Callable Wrapper • COM-Callable Wrapper (CCW) • A COM component that provides a standard COM interface and holds a reference to the .Net component it wraps. • You could build one with managed C++ using reflection-based invocation. • You don’t have to. Instead install the .net component in the GAC and use tlbexp and regasm.
Primary Interop Assembly • An interop assembly is a RCW. • It contains definitions of a COM type described in metadata. • Authors of COM components should create a primary interop assembly. • Digitally signed, installed in the GAC
Primary Interop Assembly • .Net treats the same type defined in different assemblies as different types. • Use of a Primary Interop Assembly instructs .Net that each of these are different instances of the same type. • Thus we get a single managed identity for the COM type.
Making a PIA • Use tlbimp /primary • That inserts the attribute: System.Runtime.InteropServices. PrimaryInteropAssembly • Use tlbimp /keyfile:FileName
Interop Services • Marshal Class has many static methods • QueryInterface, AddRef, Release • AllocCoTaskMem, AllocHGlobal • FreeBSTR, FreeCoTaskMem, FreeHGlobal • Many helper functions
Interop Marshaling • Interop implies two possible marshalings • COM marshaling from COM component to COM client inside a RCW • Only needed if the RCW and COM component reside in different apartments • Interop marshaling that converts a COM type to a .Net type.
Interop Marshaling Example • If the COM component interface has an [out] *BSTR, then the RCW will convert the BSTR to a System.String. • Both are unicode and length counted, but String has some additional information stored in its length prefix. • This results in a copy of the characters. • Blittable types (same memory representations) are pinned and no copy is needed. • Sbyte, Intxx, IntPtr, Byte, UIntxx, UIntPtr, Single, Double, structs with these types, C arrays with these types
Calling Methods on RCW • Method calls on the wrapper result in vtable-based calls on the COM object • Reflection with Type.InvokeMember results in an invocation through the COM object’s IDispatch interface. • See LateBinding in code folder. • HRESULT errors are mapped into .Net exceptions
COM variant IUnknown IDispatch SCODE BSTR Blittable .Net Object UnKnownWrapper DispatchWrapper ErrorWrapper String Blittable Type Correspondences
Guidelines – Designing COM Components for Interop • Designing COM components for Interop • Use dual interfaces to support early and late binding • Expose events with connection points • Expose enumerations with IEnumVARIANT • Use single-dimensional SAFEARRAYs for all arrays • Avoid variant parameters (ambiguous conversion) • Return only S_OK for success • Implement the IErrorInfo interface so exception messages are meaningful • Use threading model Both, as all .Net objects but UIs run in an MTA • If you use ApartmentThreading then you guarantee COM marshaling