net interoperability l.
Skip this Video
Loading SlideShow in 5 Seconds..
.NET Interoperability PowerPoint Presentation
Download Presentation
.NET Interoperability

Loading in 2 Seconds...

play fullscreen
1 / 32

.NET Interoperability - PowerPoint PPT Presentation

  • Uploaded on

.NET Interoperability. Liran Ben Haim Agenda. Overview P/invoke COM interop Performance What’s new in .NET framework 2.0 Questions . Overview. Platform Invoke Finding and invoking unmanaged functions

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
Download Presentation

.NET Interoperability

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
net interoperability

.NET Interoperability

Liran Ben Haim

  • Overview
    • P/invoke
    • COM interop
  • Performance
  • What’s new in .NET framework 2.0
  • Questions
  • 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
win32 api c dll
Win32 API / C DLL

using System;

using System.Runtime.InteropServices;

class PlatformInvokeTest



public static extern int puts(string c);


internal static extern int _flushall();

public static void Main()






c dll not com
C++ DLL (not COM)
  • Create a MC++ class library


  • Add 2 global functions:
    • Create object
    • Destroy object
  • Use dumpbin.exe to extract the required member functions
  • Use CallingConvention.ThisCall

class SAMP_API Csamp {

int x;


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;}

[ DllImport( "samp.dll",


CallingConvention=CallingConvention.ThisCall )]

public static extern int getnum( IntPtr ths);

[ DllImport( "samp.dll",


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);

using the object
Using the object

IntPtr p=Class1.createobject();


MessageBox.Show(Class1.getnum(p). ToString());


creating rcw
Creating RCW
  • Adding reference to a COM component in VS.NET IDE
  • Tlbimp.exe
    • Tlbimp mycom.dll
  • Custom wrapper
    • Using reflection
custom wrapper example
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);

creating ccw
Creating CCW
  • Tlbexp.exe
  • Regasm.exe
  • Register for com interop in VS.NET IDE
  • Governs how data is passed between managed and unmanaged memory during calls
  • Most data types require no conversion
    • byte
    • short
    • int
    • long
custom marshaling
Custom marshaling


public static extern int puts(


string m);

  • Or use Marshal class
marshal class
Marshal class
  • C++

typedef struct _MYSTRSTRUCT2


char* buffer;

UINT size;


void TestOutArrayOfStructs(int* pSize, MYSTRSTRUCT2** ppStruct);

[ StructLayout( LayoutKind.Sequential)]

public class MyStruct


public String buffer;

public int size;


[ DllImport( "..\\LIB\\PinvokeLib.dll" )]

public static extern void

TestOutArrayOfStructs( out int size,

out IntPtr outArray );

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 );

using unsafe code
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 );

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 );


transition performance
Transition performance
  • With every transition from managed to unmanaged code (and vice versa) there is some performance overhead
  • Platform invoke call:
    • 10 machine instructions (approx) + data marshaling time
  • COM interop call:
    • 50 machine instructions + data marshaling
  • Make Chunky Calls
string vs individual chars
String vs. individual chars

typedef struct _OSVERSIONINFOA {

DWORD dwOSVersionInfoSize;

DWORD dwMajorVersion;

DWORD dwMinorVersion;

DWORD dwBuildNumber;

DWORD dwPlatformId;

CHAR szCSDVersion[ 10 ];


[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)]

public String CSDVersion = null;


[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 {



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;


performance tips
Performance tips
  • If you can find a .NET type that satisfies your needs, make use of it
  • Primitive types require almost no marshaling at all
  • Translations from ASCII to Unicode are expensive
example messagebox
Example - MessageBox
  • 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 );

marshaling value types vs reference types
Marshaling value types vs. reference types
  • Marshaling Value types is preferable
  • Managed structures are somewhat more similar to C structures than are managed classes
  • The runtime never reorganize the field layout of managed structures
  • The GC never moves unboxed values around in memory
setlasterror field
SetLastError field

[ DllImport( "User32.dll", SetLastError=true )]

public static extern int MessageBox( IntPtr hWnd, String text, String caption, int type );

  • False in c#
  • True in VB.NET
  • Use Marshal.GetLastWin32Error();
  • Use FormatMessage() API
design considerations
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
more guidelines
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 );

code access security
Code Access Security
  • 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
more info
More info
  • Improving .NET Application Performance and Scalability

new in net framework 2 0
New In .NET Framework 2.0
  • 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

use with:


marshaling improvements
Marshaling improvements
  • The ability to wrap native function pointers into delegates
    • Marshal.GetDelegateForFunctionPointer
    • Marshal.GetFunctionPointerForDelegate
  • The ability to marshal fixed-size arrays of structures inside structures
  • [module: DefaultCharSet(CharSet.Auto)]