P/Invoke Made Easy Wei-Chen Wang.

Slides:



Advertisements
Similar presentations
Basic Java Constructs and Data Types – Nuts and Bolts
Advertisements

Copyright © 2008 Pearson Education, Inc. Publishing as Pearson Addison-Wesley Chapter 12 Introduction to ASP.NET.
Error-handling using exceptions
Twenty C# Questions Explained Gerry O’Brien Content Development Manager Paul Pardi Senior Content Pub Manager.
Purpose : To convert this string to a new character array. Return Type : char[ ] Parameters : none Declaration : public char[ ] toCharArray() Returns.
Dynamic Memory Allocation in C.  What is Memory What is Memory  Memory Allocation in C Memory Allocation in C  Difference b\w static memory allocation.
Computer Programming and Basic Software Engineering 9 Building Graphical User Interface Developing a Simple Graphical User Interface (GUI)
What's new in Microsoft Visual C Preview
Algorithms and data structures
David Notkin Autumn 2009 CSE303 Lecture 13 This space for rent.
Programming Languages and Paradigms The C Programming Language.
ASP.NET Best Practices Dawit Wubshet Park University.
C# Language Report By Trevor Adams. Language History Developed by Microsoft Developed by Microsoft Principal Software Architect Principal Software Architect.
CERTIFICATION OBJECTIVES Use Class Members Develop Wrapper Code & Autoboxing Code Determine the Effects of Passing Variables into Methods Recognize when.
Various languages….  Could affect performance  Could affect reliability  Could affect language choice.
Memory allocation CSE 2451 Matt Boggus. sizeof The sizeof unary operator will return the number of bytes reserved for a variable or data type. Determine:
.NET.NET Interoperability Liran Ben Haim
Best Practices for Interop with Visual C++ Boris Jabes Program Manager Microsoft Corporation.
P/Invoke Made Easy Wei-Chen Wang. Marshaling governs how data is passed between managed and unmanaged memory during platform invoke. Function Call Interop.
6/10/2015C++ for Java Programmers1 Pointers and References Timothy Budd.
George Blank University Lecturer. CS 602 Java and the Web Object Oriented Software Development Using Java Chapter 4.
C#.NET C# language. C# A modern, general-purpose object-oriented language Part of the.NET family of languages ECMA standard Based on C and C++
Run time vs. Compile time
ספטמבר 04Copyright Meir Kalech1 C programming Language Chapter 10: Appendices.
C#/.NET Jacob Lewallen. C# vs.NET.NET is a platform. Many languages compile to.NET: –VB.NET –Python.NET –Managed C++ –C#
C and Data Structures Baojian Hua
1 CSE 303 Lecture 11 Heap memory allocation ( malloc, free ) reading: Programming in C Ch. 11, 17 slides created by Marty Stepp
Introducing the Common Language Runtime for.NET. The Common Language Runtime The Common Language Runtime (CLR) The Common Language Runtime (CLR) –Execution.
Introducing the Common Language Runtime. The Common Language Runtime The Common Language Runtime (CLR) The Common Language Runtime (CLR) –Execution engine.
Memory Layout C and Data Structures Baojian Hua
Java Data Types  Everything is an Object  Except Primitive Data Types  For efficiency  Platform independent  Portable  “slow”  Objects are often.
CMSC 341 Introduction to Java Based on tutorial by Rebecca Hasti at
Differences between C# and C++ Dr. Catherine Stringfellow Dr. Stewart Carpenter.
University of Washington CSE 351 : The Hardware/Software Interface Section 5 Structs as parameters, buffer overflows, and lab 3.
1 CISC181 Introduction to Computer Science Dr. McCoy Lecture 19 Clicker Questions November 3, 2009.
Security Exploiting Overflows. Introduction r See the following link for more info: operating-systems-and-applications-in-
Chapter 6 Buffer Overflow. Buffer Overflow occurs when the program overwrites data outside the bounds of allocated memory It was one of the first exploited.
Managed C++. Objectives Overview to Visual C++.NET Concepts and architecture Developing with Managed Extensions for C++ Use cases Managed C++, Visual.
Java Introduction to JNI Prepared by Humaira Siddiqui.
By Noorez Kassam Welcome to JNI. Why use JNI ? 1. You already have significantly large and tricky code written in another language and you would rather.
CS212: Object Oriented Analysis and Design Lecture 6: Friends, Constructor and destructors.
Dynamic Memory Allocation Conventional array and other data declarations An incorrect attempt to size memory dynamically Requirement for dynamic allocation.
CMPSC 16 Problem Solving with Computers I Spring 2014 Instructor: Tevfik Bultan Lecture 12: Pointers continued, C strings.
Computer Science and Software Engineering University of Wisconsin - Platteville 2. Pointer Yan Shi CS/SE2630 Lecture Notes.
Software Engineering in Robotics Interfacing to external functions Henrik I. Christensen –
Advanced C# Eric Gunnerson Program Manager Visual C#.NET Microsoft Corporation.
Effective C# 50 Specific Ways to Improve Your C# Item 46~ /09/25 1.
Chapter 7 Pointers: Java does not have pointers. Used for dynamic memory allocation.
1 9/6/05CS360 Windows Programming CS360 Windows Programming.
Managing C++ CHRIS DAHLBERG MID-TIER DEVELOPER SCOTTRADE.
Object Oriented Software Development 4. C# data types, objects and references.
EEL 3801 C++ as an Enhancement of C. EEL 3801 – Lotzi Bölöni Comments  Can be done with // at the start of the commented line.  The end-of-line terminates.
DEV394.NET Framework: Migrating To Managed Code Adam Nathan QA Lead Richard Lander Program Manager Microsoft Corporation.
Introduction to C# Anders Hejlsberg Distinguished Engineer Developer Division Microsoft Corporation.
Announcements There is a Quiz today. There were problems with grading assignment 2, but they should be worked out today The web page for correcting the.
CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics Advanced.NET Programming II 5 th Lecture Pavel Ježek
CHARLES UNIVERSITY IN PRAGUE faculty of mathematics and physics Advanced.NET Programming II 3 rd Lecture Pavel Ježek
Recap Resizing the Vector Push_back function Parameters passing Mechanism Primitive Arrays of Constants Multidimensional Arrays The Standard Library string.
INTRODUCTION BEGINNING C#. C# AND THE.NET RUNTIME AND LIBRARIES The C# compiler compiles and convert C# programs. NET Common Language Runtime (CLR) executes.
Object Lifetime and Pointers
Static data members Constructors and Destructors
Advanced .NET Programming II 4th Lecture
Native / Managed Interop
COMPUTER 2430 Object Oriented Programming and Data Structures I
CSC 253 Lecture 8.
CSC 253 Lecture 8.
AVG 24th 2015 ADVANCED c# - part 1.
Memory Allocation CS 217.
Pointers C#, pointers can only be declared to hold the memory addresses of value types int i = 5; int *p; p = &i; *p = 10; // changes the value of i to.
Paul Stubbs MCSD, MCSE 4.0, MCP+I, MCT, MCAD .Net
Presentation transcript:

P/Invoke Made Easy Wei-Chen Wang

Interop Marshaling Marshaling governs how data is passed between managed and unmanaged memory during platform invoke. Managed Client Out Parameters Unmanaged Library Function Call In Parameters

Pass Parameters 3 ways to transfer parameters between managed code and unmanaged code Marshaling the data by Marshaler Allocating an unmanaged memory block, populating the data, and passing the address of the memory block Just passing the address of the managed object without marshaling the object

The unsafe Way /* C# Wrapper */ struct MyStruct { Int32 num; IntPtr str1; } [DllImport("dll.dll")] void func(IntPtr ms); /* C Declarations */ struct MyStruct { DWORD num; LPWSTR str1; } void func(struct MyStruct *ms); unsafe { IntPtr ms = Marshal.AllocHGlobal(sizeof(MyStruct)); MyStruct *pms = (MyStruct*)ms; ms->a = MAGIC_NUMBER; ms->str1 = Marshal.AllocHGlobal(MAGIC_STRING.length*2); strcpy( ms->str1, MAGIC_STRING); func( ms ); } directly operate the object via pointer pass the address, IntPtr, of the struct

A Better Way /* C# Wrapper */ struct MyStruct { Int32 num; IntPtr str1; } [DllImport("dll.dll")] void func(IntPtr ms); /* C Declarations */ struct MyStruct { DWORD num; LPWSTR str1; } void func(struct MyStruct *ms); { IntPtr pms = Marshal.AllocHGlobal(sizeof(MyStruct)); MyStruct ms; ms.num = MAGIC_NUMBER; ms.str1 = Marshal.StringToHGlobalUni(MAGIC_STRING); Marshal.StructureToPtr(ms, pms, false); func(ms); } operate the managed object allocate memory and copy string by Mashaler utility

Summary, So Far... unsafe code is hard to write (in C#), hard to debug, and lack of compiling-time and runtime checking. In most case, we don't have to use unsafe pointers. We should operate everything on managed objects, and convert them to unmanaged objects only when we want to perform platform invoke. It is free to encapsulate the converting code as methods of the object. Methods won't change the memory layout of the object. Using AllocHGlobal to manually allocate an unmanaged memory block is necessary, if we want to pass the object for an asynchronous call.

Marshaling by Marshaler (the best way) /* C# Wrapper */ struct MyStruct { Int32 num; [MarshalAs(UnmanagedType.LPWStr)] String str1; } [DllImport("dll.dll")] void func(ref MyStruct ms); /* C Declarations */ struct MyStruct { DWORD num; LPWSTR str1; } void func(struct MyStruct *ms); indicate the string should be converted to a pointer, which points to a string buffer { MyStruct ms; ms.num = MAGIC_NUMBER; ms.str = MAGIC_STRING; func(ref ms); } num operate on managed object str1 string the Marsahler will convert it to unmanaged object for you

Marshaling Internals Managed Memory Stack Stack Parameters Heap Heap Unmanaged Memory 2. Marshal managed In-parameters to native Stack Stack Parameters 6. Clean up managed Out-parameters 4. native code operate on unmanaged object Heap Heap Object Object 8. Clean up native data Object 7. Marshal native Out-parameters to managed Code Code 1. Call C# wrapper 3. Call native code C# Wrapper() Function() 9. Return from C# wrapper 5. Return from native code

Default Marshaling for Blittable Types struct MyStruct { Int32 a; Int32 b; public MyStruct(Int32 _a, Int32 _b) { a = _a; b = _b; } } [DllImport("dll.dll")] void CFunction(ref MyStruct ms); MyStruct ms = new MyStruct(MAGIC_A, MAGIC_B); CFunction(ref ms); struct MyStruct { DWORD a; DWORD b; }; void f(struct MyStruct *ms);

Default Marshaling for Blittable Types Managed Memory Unmanaged Memory 3. Pass the address (call-by-reference) Stack Stack Parameters 5. native code operate on managed object Heap Heap 2. Pin the object Object 7. Un-Pin the object Code Code 1. Call C# wrapper 4. Call native code C# Wrapper() Function() 8. Return from C# wrapper 6. Return from native code

Write Your Own Marshaler class MyClass { /* ... */ } class MyClassMarshaler: ICustomMarshaler { public void CleanUpManagedData(object ManagedObj); public void CleanUpNativeData(IntPtr pNativeData); public IntPtr MarshalManagedToNative(object ManagedObj); public object MarshalNativeToManaged(IntPtr pNativeData); } [DllImport("dll.dll")] static extern void Function( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(MyClassMarshaler))] MyClass mc ); Custom marshaler used For marshaling MyClass Use MyClassMarshaler to marshal MyClass

ICustomMarshaler in Action Managed Memory Unmanaged Memory Stack 2. MarshalManaged ToNative() Stack Parameters 3. CleanUp ManagedData() Heap Heap Object Object 5. CleanUp NativeData() Object 4. MarshalNative ToManaged() 1. GetInstance() to get a instance of the marshaler Code Code 3. Call/Return from native code C# Wrapper() Function()

Delegate/Callback Managed Memory Stack Stack Parameters Heap delegate 2. pass delegate marshaled as a function pointer Unmanaged Memory Stack Stack Parameters Heap delegate marshaling parameters Code Code 5. return from callback delegate() callback() 1. Call C# wrapper 4. invoke callback 3. Call native code C# Wrapper() Function() 7. Return from C# wrapper 6. Return from native code

Windows String at A Glance ANSI String=char array=user locale encoding Unicode String=wchar array=UTF-16 Little-Endian (Unicode is not necessary UTF-16LE, but in Windows, it is) T-String=TCHAR array, char or wchar depends on compiling configuration WINUSERAPI int WINAPI MessageBoxA( __in_opt HWND hWnd, __in_opt LPCSTR lpText, __in_opt LPCSTR lpCaption, __in UINT uType); WINUSERAPI int WINAPI MessageBoxW( __in_opt HWND hWnd, __in_opt LPCWSTR lpText, __in_opt LPCWSTR lpCaption, __in UINT uType); #ifdef UNICODE #define MessageBox MessageBoxW #else #define MessageBox MessageBoxA #endif // !UNICODE

More on Marshaling String [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] struct MyStruct { [MarshalAs(UnmanagedType.LPStr)] string str1; [MarshalAs(UnmanagedType.LPWStr)] string str2; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = N)] string str3; } struct MyStruct { LPSTR str1; LPWSTR str2; WCHAR str3[N]; }; Just pass the struct. The marshaler will do the rest for you MyStruct ms; ms.str1 = "Hello"; ms.str2 = "world"; ms.str3 = "!!!"; function( ref ms);

Get a String Out void GetString( LPWSTR *text, int nMaxCount ); 1 [DllImport("dll.dll")] static extern void GetString(out String text, int nMaxCount); The memory allocated on text in GetString() will leak. Don't Do It! 2 [DllImport("dll.dll")] static extern void GetString(ref String text, int nMaxCount); You cannot specify the size of the output buffer. Don't Do It Too void GetString( LPWSTR text, int nMaxCount ); 3 [DllImport("dll.dll")] static extern void GetString(StringBuilder text, int nMaxCount); Just Do It ü StringBuilder sbtext = new Stringbuilder(STR_LENGTH); GetString( sbtext, sbtext.Capacity );

InAttribute and OutAttribute InAttribute indicates that data should be marshaled from the caller to the callee, but not back to the caller OutAttribute indicates that data should be marshaled from callee back to caller Use the proper attributes to reduce unnecessary data copy /* Example */ [DllImport("mydll.dll")] static extern void func([in] ref MyStruct); // pass the reference(pointer) of the structure // parameter will be copied in, but not out

Keep Objects in Memory Local variable can be garbage collected as it reach a point where it appears no longer being referenced { MyFile file = new MyFile("file.txt"); IntPtr h = file.Handle; // file is eligible for finalization after push the parameter WriteFile( file.Handle ); } Suppose that MyFile will close the file handle when finalizing, hence the file handle will be invalid.

Solutions 1 { MyFile file = new MyFile("file.txt"); IntPtr h = file.Handle; DoSomething(h); GC.KeepAlive(file); } The purpose of KeepAlive is to keep a reference the object. Besides that, KeepAlive have no side-effect. 2 { MyFile file = new MyFile("file.txt"); IntPtr h = file.Handle; GCHandle gh = GCHnalde.Alloc(file); DoSomething(h); gh.Free(); } Allocating a GCHandle prevents the object from being collected. 3 { MyFile file = new MyFile("file.txt"); IntPtr h = file.Handle; PInvoke(new HandleRef(file, h)); } HandleRef guarantees that the object is not collected until the p/invoke completes

GCHandle GCHandle can be used to prevent an objects being garbage collected pin an object in memory, so it won't be relocated by GC (the object has to be of a value-type) get the address of a pinned object

Pin an Object Only blittable object can be pinned. struct PinMe { int a; int b; } void PinYou() { struct PinMe pm; pm.a = MAGIC_NUM1; pm.b = MAGIC_NUM2; GCHandle gh = GCHandle.Alloc(pm, GCHandleType.Pinned); CFunction(gh.AddrOfPinnedObject()); gh.Free(); } Only blittable object can be pinned. The only reason to pin an blittable object it that you want to pass it to unmanaged code for an asynchronous operation, hence you don't want GC relocate it. manipulate the managed object in un managed code, CFunction()

Get the Handle of an Object We can't manipulate a managed object in unmanaged code, but we can pass the handle of it between managed and unmanaged code as callback data. void function() { Object obj = new Object(); GCHandle gh = GCHandle.Alloc(obj); CFunction( GCHandle.ToIntPtr(gh), Callback ); } void Callback(IntPtr p) GCHandle gh = GCHandle.FromIntPtr(p); Object obj = gh.Target; gh.Free(); }

References Interop Marshaling http://msdn.microsoft.com/en-us/library/04fy9ya1.aspx Marshaling Data with Platform Invoke http://msdn.microsoft.com/en-us/library/fzhhdwae.aspx Blittable and Non-Blittable Types http://msdn.microsoft.com/en-us/library/75dwhxf7.aspx HandleRef Structure http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.handleref.aspx SafeHandles: the best V2.0 feature of the .NET Framework https://blogs.msdn.com/bclteam/archive/2005/03/15/396335.aspx SafeHandle: A Reliability Case Study http://blogs.msdn.com/bclteam/archive/2005/03/16/396900.aspx The Truth About GCHandles http://blogs.msdn.com/clyon/archive/2005/03/18/398795.aspx GCHandle.ToIntPtr vs. GCHandle.AddrOfPinnedObject http://blogs.msdn.com/jmstall/archive/2006/10/09/gchandle_5F00_intptr.aspx GCHandles, Boxing and Heap Corruption http://blogs.msdn.com/clyon/archive/2004/09/17/230985.aspx SafeHandle: A Reliability Case Study [Brian Grunkemeyer] http://blogs.msdn.com/bclteam/archive/2005/03/16/396900.aspx