Download presentation
Presentation is loading. Please wait.
1
.NET.NET Interoperability Liran Ben Haim liran@bna.co.il http://www.bna.co.il
2
2 Agenda Overview Overview P/invoke COM interop Performance Performance What’s new in.NET framework 2.0 What’s new in.NET framework 2.0 Questions Questions
3
3 Overview Platform Invoke Finding and invoking unmanaged functions Marshaling managed arguments to and from unmanaged code COM Interoperability Runtime Callable Wrapper (RCW) Used by managed clients to call a method on a COM object COM Callable Wrapper (CCW) Used by COM clients to call a method on a managed object
4
4 Win32 API / C DLL using System; using System.Runtime.InteropServices; class PlatformInvokeTest { [DllImport("msvcrt.dll")] [DllImport("msvcrt.dll")] public static extern int puts(string c); public static extern int puts(string c); [DllImport("msvcrt.dll")] [DllImport("msvcrt.dll")] internal static extern int _flushall(); internal static extern int _flushall(); public static void Main() public static void Main() { puts("Test"); puts("Test"); _flushall(); _flushall(); }}
5
5 C++ DLL (not COM) Create a MC++ class library Create a MC++ class libraryOr Add 2 global functions: Add 2 global functions: Create object Destroy object Use dumpbin.exe to extract the required member functions Use dumpbin.exe to extract the required member functions Use CallingConvention.ThisCall Use CallingConvention.ThisCall
6
6 Example class SAMP_API Csamp { int x; public: int getnum(void){return x;} void setnum(int x1){x=x1;} }; extern "C" Csamp SAMP_API *createobject() {return new Csamp;} extern "C" void SAMP_API deleteobject(Csamp *p) {delete p;} {delete p;}
7
7 [ DllImport( "samp.dll", EntryPoint="?getnum@Csamp@@QAEHXZ", EntryPoint="?getnum@Csamp@@QAEHXZ", CallingConvention=CallingConvention.ThisCall )] CallingConvention=CallingConvention.ThisCall )] public static extern int getnum( IntPtr ths); [ DllImport( "samp.dll", EntryPoint="?setnum@Csamp@@QAEXH@Z", EntryPoint="?setnum@Csamp@@QAEXH@Z", CallingConvention=CallingConvention.ThisCall )] CallingConvention=CallingConvention.ThisCall )] public static extern void setnum( IntPtr ths,int n); [ DllImport( "samp.dll" )] public static extern IntPtr createobject(); [ DllImport( "samp.dll" )] public static extern void deleteobject(IntPtr p);
8
8 Using the object IntPtr p=Class1.createobject(); Class1.setnum(p,77); MessageBox.Show(Class1.getnum(p). ToString()); Class1.deleteobject(p);
9
9 Creating Creating RCW Adding reference to a COM component in VS.NET IDE Adding reference to a COM component in VS.NET IDE Tlbimp.exe Tlbimp.exe Tlbimp mycom.dll Custom wrapper Custom wrapper Using reflection
10
10 Custom wrapper example Type excel; object[] parameter= new object[1]; object excelObject; excel = Type.GetTypeFromProgID("Excel.Application"); excelObject = Activator.CreateInstance(excel); parameter[0] = true; excel.InvokeMember("Visible", BindingFlags.SetProperty, null, excelObject, parameter);
11
11 Creating CCW Tlbexp.exe Tlbexp.exe Regasm.exe Regasm.exe Register for com interop in VS.NET IDE Register for com interop in VS.NET IDE
12
12 Marshaling Governs how data is passed between managed and unmanaged memory during calls Governs how data is passed between managed and unmanaged memory during calls Most data types require no conversion Most data types require no conversion byte short int long …
13
13 Custom marshaling [DllImport("msvcrt.dll")] public static extern int puts( [MarshalAs(UnmanagedType.LPStr)] [MarshalAs(UnmanagedType.LPStr)] string m); string m); Or use Marshal class Or use Marshal class
14
14 Marshal class C++ C++ typedef struct _MYSTRSTRUCT2 { char* buffer; UINT size; } MYSTRSTRUCT2; void TestOutArrayOfStructs(int* pSize, MYSTRSTRUCT2** ppStruct); void TestOutArrayOfStructs(int* pSize, MYSTRSTRUCT2** ppStruct);
15
15 [ StructLayout( LayoutKind.Sequential)] public class MyStruct { public String buffer; public int size; } [ DllImport( "..\\LIB\\PinvokeLib.dll" )] public static extern void TestOutArrayOfStructs( out int size, outIntPtr outArray );
16
16 int size; IntPtr outArray; LibWrap.TestOutArrayOfStructs( out size, out outArray ); MyStruct[] manArray = new MyStruct[ size ]; IntPtr current = outArray; for( int i = 0; i < size; i++ ) { manArray[ i ] = new MyStruct(); Marshal.PtrToStructure( current, manArray[ i ]); Marshal.DestroyStructure( current, typeof(MyStruct) ); current = (IntPtr)((int)current + Marshal.SizeOf( manArray[ i ] )); } Marshal.FreeCoTaskMem( outArray );
17
17 Using unsafe code [ StructLayout( LayoutKind.Sequential )] public struct MyUnsafeStruct { public IntPtr buffer; public int size; } [ DllImport( "..\\LIB\\PinvokeLib.dll" )] public static extern void TestOutArrayOfStructs( out int size, MyUnsafeStruct** outArray );
18
18 public static unsafe void UsingUnsafe() { int size; MyUnsafeStruct* pResult; LibWrap.TestOutArrayOfStructs( out size, &pResult ); MyUnsafeStruct* pCurrent = pResult; for( int i = 0; i < size; i++, pCurrent++ ) { Console.WriteLine( "Element {0}: {1} {2}", i, Marshal.PtrToStringAnsi( pCurrent->buffer ), pCurrent->size ); Marshal.FreeCoTaskMem( pCurrent->buffer ); } Marshal.FreeCoTaskMem( (IntPtr)pResult ); }
19
19 Transition performance With every transition from managed to unmanaged code (and vice versa) there is some performance overhead With every transition from managed to unmanaged code (and vice versa) there is some performance overhead Platform invoke call: Platform invoke call: 10 machine instructions (approx) + data marshaling time COM interop call: COM interop call: 50 machine instructions + data marshaling Make Chunky Calls Make Chunky Calls
20
20 String vs. individual chars typedef struct _OSVERSIONINFOA { DWORD dwOSVersionInfoSize; DWORD dwMajorVersion; DWORD dwMinorVersion; DWORD dwBuildNumber; DWORD dwPlatformId; CHAR szCSDVersion[ 10 ]; } OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA;
21
21 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] class OSVersionInfo { public UInt32 OSVersionInfoSize = (UInt32) Marshal.SizeOf(typeof(OSVersionInfo)); public UInt32 MajorVersion = 0; public UInt32 MinorVersion = 0; public UInt32 BuildNumber = 0; public UInt32 PlatformId = 0; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public String CSDVersion = null; }
22
22 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] internal struct OSVersionInfoBlittable { public UInt32 OSVersionInfoSize; public UInt32 MajorVersion; public UInt32 MinorVersion; public UInt32 BuildNumber; public UInt32 PlatformId; unsafe public String CSDVersion { get { fixed (Char* str = &CSDVersion0) { return new String(str); } }} Char CSDVersion0; Char CSDVersion1; Char CSDVersion2; Char CSDVersion3; Char CSDVersion4; Char CSDVersion5; Char CSDVersion6; Char CSDVersion7; Char CSDVersion8; Char CSDVersion9; }
23
23 Performance tips If you can find a.NET type that satisfies your needs, make use of it If you can find a.NET type that satisfies your needs, make use of it Primitive types require almost no marshaling at all Primitive types require almost no marshaling at all Translations from ASCII to Unicode are expensive Translations from ASCII to Unicode are expensive
24
24 Example - MessageBox 2 functions: 2 functions: MessageBoxA - ansi MessageBoxW – unicode [ DllImport( "User32.dll", EntryPoint="MessageBoxW", CharSet=CharSet.Unicode, ExactSpelling=true )] public static extern int MsgBox( int hWnd, String text, String caption, uint type );
25
25 Marshaling value types vs. reference types Marshaling Value types is preferable Marshaling Value types is preferable Managed structures are somewhat more similar to C structures than are managed classes Managed structures are somewhat more similar to C structures than are managed classes The runtime never reorganize the field layout of managed structures The runtime never reorganize the field layout of managed structures The GC never moves unboxed values around in memory The GC never moves unboxed values around in memory
26
26 SetLastError field [ DllImport( "User32.dll", SetLastError=true )] public static extern int MessageBox( IntPtr hWnd, String text, String caption, int type ); False in c# False in c# True in VB.NET True in VB.NET Use Marshal.GetLastWin32Error(); Use Marshal.GetLastWin32Error(); Use FormatMessage() API Use FormatMessage() API
27
27 Design Design Considerations Design chunky interfaces to avoid round trips. Reduce round trips with a facade. Implement IDisposable if you hold unmanaged resources across client calls. Reduce or avoid the use of late binding and reflection. In ASP.NET – Server.CreateObject or Server.CreateObjectFromClsid
28
28 More guidelines Use IntPtr for manual marshaling. Use [in] and [out] to avoid unnecessary marshaling. [DllImport("gdi32.dll", CharSet=CharSet.Auto)] public static extern int CreateFontIndirect( [In, MarshalAs(UnmanagedType.LPStruct)] LOGFONT lplf );
29
29 Use SuppressUnmanagedCode for performance-critical trusted scenarios [DllImport("kernel32.dll"), SuppressUnmanagedCodeSecurity] public static extern bool Beep(int frequency, int duration); Allows managed code to call into unmanaged code without a stack walk TLBIMP /unsafe disable the full CAS stack walk for the unmanaged code Code Access Security
30
30 More info Improving.NET Application Performance and Scalability Improving.NET Application Performance and Scalability http://msdn.microsoft.com/library/default.asp?url=/library/en- us/dnpag/html/scalenetchapt07.asp http://msdn.microsoft.com/library/default.asp?url=/library/en- us/dnpag/html/scalenetchapt07.asp
31
31 New In.NET Framework 2.0 C++/CLI will include some useful templates for simplifying C++ interop C++/CLI will include some useful templates for simplifying C++ interop The new SafeHandle class, provide safe and reliable means of manipulating operating system handles The new SafeHandle class, provide safe and reliable means of manipulating operating system handles use with: [MethodImpl(MethodImplOptions.MustRun)]
32
32 The ability to wrap native function pointers into delegates The ability to wrap native function pointers into delegates Marshal.GetDelegateForFunctionPointer Marshal.GetFunctionPointerForDelegate The ability to marshal fixed-size arrays of structures inside structures The ability to marshal fixed-size arrays of structures inside structures [module: DefaultCharSet(CharSet.Auto)] [module: DefaultCharSet(CharSet.Auto)] Marshaling improvements
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.