Upload
karmamen
View
217
Download
0
Tags:
Embed Size (px)
DESCRIPTION
A
Citation preview
Unsafe Code and Interoperability 1C# 30
C# 3.0C# 3.0
Chapter 22 Unsafe Code and InteroperabilityInteroperability
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Interoperability IntroductionUnsafe Code and Interoperability 2C# 30
Interoperability IntroductionInteroperabilit is the abilit to ha e Interoperability is the ability to have managed code and unmanaged code work g gtogether in one application
Managed code is code that requires the execution Managed code is code that requires the execution environment of the Common Language RuntimeU d d i d th t d t d th CLR Unmanaged code is code that does not need the CLR
Unmanaged code is outside the reach of the CLRs management servicesmanagement services
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
NET Interoperability OptionsUnsafe Code and Interoperability 3C# 30
.NET Interoperability OptionsThe NET pro ides s ith three main The .NET provides us with three main interoperability options:p y p Calling C DLL functions from a .NET component
This service is termed Platform InvokeThis service is termed Platform Invoke
Interoperability with COM objects A NET program invokes methods on a COM object A .NET program invokes methods on a COM object A non-.NET program invokes methods on a .NET
object as if it were a COM objectobject as if it were a COM object Mixing managed and unmanaged code using the C++
NET version: C++/CLI.NET version: C++/CLI
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
NET Interoperability ServicesUnsafe Code and Interoperability 4C# 30
.NET Interoperability Services The core interoperability services are The core interoperability services are
performed by the CLR The .NET framework provides us with several
Interoperability APIs (attributes and helper classes)i i System.Runtime.InteropServices
In this course we will see how to use the In this course we will see how to use the Platform Invoke (P/Invoke) mechanism
COM Interop and C++/CLI are out of theCOM Interop and C /CLI are out of the scope of this course
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Using Pointers Within C# CodeUnsafe Code and Interoperability 5C# 30
Using Pointers Within C# CodeBefore getting into the interoperabilit Before getting into the interoperability subjects:j We will examine pointers within C# code Pointers may be useful through interoperability Pointers may be useful through interoperability
operations, and may improve performance
C# id f C# provides references References lead to safe code They are guaranteed to refer to valid objects
Pointers are not safe Pointers are not safe
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Using Pointers Within C# CodeUnsafe Code and Interoperability 6C# 30
Using Pointers Within C# Code Pointers are defined with the familiar C Pointers are defined with the familiar C
syntax Pointers may refer to any address in memory C# allows pointers to be defined only in an unsafe
context Such a context is declared by using the unsafe
k dkeyword
publicunsafe voidfunc(int x)publicunsafe voidfunc(int x){
int* px =&x;}}
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Using Pointers Within C# CodeUnsafe Code and Interoperability 7C# 30
Using Pointers Within C# Code Almost anything can be marked as unsafe: Almost anything can be marked as unsafe:
An entire type (class, struct, interface or delegate) A specific member (field, method, property, event,
indexer, operator, constructor, static constructor, or finalizer)finalizer)
A code block can be declared as unsafe
Th d ill l il if th / f The code will only compile if the /unsafecompiler option is specifiedp p p
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
What Can Pointers Point To?Unsafe Code and Interoperability 8C# 30
What Can Pointers Point To? Pointers can only point to blittable types Pointers can only point to blittable types
Primitive types Value types with no references (recursively) Pointer Types (i.e., pointer to a pointer) void *
You can take the address of a field withinYou can take the address of a field within an object or an array elementpublicstaticunsafevoidfunc(int[]a){
i t* //Thi d NOT il !int*pa=a;//ThisdoesNOTcompile!}
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
The fixed StatementUnsafe Code and Interoperability 9C# 30
The fixed Statement To take the address of a moveable object To take the address of a moveable object,
you must use fixed The fixedstatement does two things:
Enables the assignment of the address of a moveableEnables the assignment of the address of a moveable variable to a pointer
Declares a block of code in which the CLRDeclares a block of code in which the CLR guarantees not to move the moveable variable
The variable is considered to be pinned in memory
publicstaticunsafevoidfunc(int[]a){fixed (int*pa=a)( p ){
*pa=17;//ThisDOEScompile!}
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
}}
fixed Additional NotesUnsafe Code and Interoperability 10C# 30
fixed Additional Notes You can initialize more than one pointer in You can initialize more than one pointer in
a single fixed statement If they are of the same type Otherwise, fixed statements must be nested
int[]b=newint[3];strings="Hello";fixed(int* pa=a,pb =b) {ed ( t pa a, pb b) {
*pa=17;*pb =18;//Lik C dC i i St i df '&'//LikeCandC++,assigningaString,noneedfor'&'fixed(char*ps =s){{
*ps ='Y';//Donttrythisathome!}
}
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
}
Unsafe Code and Interoperability 11C# 30
Platform InvokePlatform Invoke
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Platform InvokeUnsafe Code and Interoperability 12C# 30
Platform Invoke Consider the following C function which Consider the following C function which
tests whether a number is prime:int IsPrime(int num);
This function returns a non-zero value to indicate true, and zero (0) to indicate false
Can this function be called from C#?Can this function be called from C#? Yes! See the code on the next slide
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Calling IsPrime from C#Unsafe Code and Interoperability 13C# 30
Calling IsPrime from C#usingSystem Runtime InteropServices;usingSystem.Runtime.InteropServices;publicclassTest{
[DllImport("GoodOldCFunctions.dll")][ p ( )]publicstaticexternbool IsPrime(int num);
}classProgram{classProgram{
staticvoidMain(string[]args){Console.WriteLine("Primenumbers:");( );for(int i =0;i
Behind the ScenesUnsafe Code and Interoperability 15C# 30
Behind the ScenesAt r ntime the DLL is loaded into memor At runtime, the DLL is loaded into memory If it is not found, an exception will be thrown
An entry point with the name of the function is located within the DLLfunction is located within the DLL If this is not found, a different exception will be thrown
C# parameters are converted to match standard C conventionsstandard C conventions
The function is called and its return valueThe function is called and its return value is converted back
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Marshaling Data TypesUnsafe Code and Interoperability 16C# 30
Marshaling Data TypesThe NET pro ided arg ments sho ld be The .NET provided arguments should be marshaled to the C function parametersp The C function return value should be marshaled to
the .NET calling functionthe .NET calling function
Understanding the marshaling principles is fessential for using interoperability
Based on the C function signature and the ginteroperability marshaling rules we can correctly create the appropriate C# function declarationpp p
Use pinvoke.net or the P/Invoke Interop Assistant
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
P/Invoke Interop AssistantUnsafe Code and Interoperability 17C# 30
P/Invoke Interop AssistantOpen so rce Microsoft tool for generating Open-source Microsoft tool for generating P/Invoke signaturesg Has a database of Windows API functions Can parse a C/C++ header file Can parse a C/C++ header file Download from: http://www.codeplex.com/clrinterop
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Isomorphic and Non-isomorphicUnsafe Code and Interoperability 18C# 30
Isomorphic and Non-isomorphicSome C# t pes are implemented in the Some C# types are implemented in the same way that C implements themy p For example, int in C# (System.Int32) is
implemented in the same way as a native C intp e e ted t e sa e ay as a at e C t Such a type is known as Isomorphic or Blittable
No conversion is necessary when passed into a C function No conversion is necessary when passed into a C function
Other types are not implemented in the same way as in C bool (System.Boolean) or string (System.String)bool (System.Boolean) or string (System.String)
These are known as Non-isomorphic or Non-blittabletypes
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
yp
Type MappingsUnsafe Code and Interoperability 19C# 30
Type Mappings
C# Type
Framework Name Isomorphic Matching C Type
float System.Single Yes floatdouble System.Double Yes doublesbyte System.SByte Yes signedcharbyte System.Byte Yes unsignedcharshort System.Int16 Yes shortushort System.UInt16 Yes unsignedshortint System.Int32 Yes intuint System.UInt32 Yes unsignedinty glong System.Int64 Yes __int64ulong System.UInt64 Yes unsigned int64
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
ulong System.UInt64 Yes unsigned__int64
Type MappingsUnsafe Code and Interoperability 20C# 30
Type MappingsC# T F k I hi M t hi C TC# Type Framework
NameIsomorphic Matching C Type
bool System Boolean No intbool System.Boolean No intchar System.Char No char or wchar_tstring System Boolean No char* orstring System.Boolean No char* or
wchar_t* (or BSTRfor COM))
object System.Object No VARIANT (COM interoperability only)
1D-array of i hi
Yes Array of equivalent i hiisomorphic isomorphic
Other arrays No Interface or SAFEARRAY (COM)
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
SAFEARRAY (COM)
String ConversionsUnsafe Code and Interoperability 21C# 30
String Conversions Converting simple non isomorphic types Converting simple non-isomorphic types
like bool is an easy task for the runtime There is a one-to-one mapping between these types
Converting a string is more complicatedConverting a string is more complicated .NET strings are implemented as a set of Unicode
characterscharacters Strings in C are usually implemented as
char* (ANSI strings) or wchar t* (Unicode) strings( g ) _ ( ) g
The default is to assume that C expects ANSI strings Thus by default C# strings undergo a conversion beforeThus, by default C# strings undergo a conversion, before
being passed
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
String ExampleUnsafe Code and Interoperability 22C# 30
String ExampleConsider the follo ing C f nction hich Consider the following C function which counts the number of digits in a string:g g
Th di C# d l ti iint CountDigits(char*text);
The corresponding C# declaration is:[DllImport("GoodOldCFunctions.dll")]
Wh t h ld d if th C f ti
[ p ( )]publicstaticexternint CountDigits(stringtext);
What should we do if the C function expected Unicode characters?p
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
DllImportAttribute FieldsUnsafe Code and Interoperability 23C# 30
DllImportAttribute FieldsThe DllImportAttrib te class has The DllImportAttribute class has some properties which can be used to p poverride the default behavior
The property CharSet can be used to indicate how The property CharSet can be used to indicate how strings should be passedTh l l l f thi t f th The legal values for this property come from the CharSet enumeration which contains:
A i (d f lt) Ansi (default) UnicodeAuto Auto
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Using CharSetUnsafe Code and Interoperability 24C# 30
Using CharSet
Thi C f ti t U i d t i This C function expects a Unicode string:int IsTextAllInGreek(wchar_t*text);
The corresponding C# declaration is:[DllImport(OldCFunctions.dll",CharSet=CharSet.Unicode)]publicstaticexternbool IsTextAllInGreek(stringtext);
This causes the runtime to pass the C# string as a Unicode string to the C functionas a Unicode string to the C function
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
The MarshalAs AttributeUnsafe Code and Interoperability 25C# 30
The MarshalAs AttributeUsually the CharSet field of the Usually the CharSet field of the DllImport attribute is enough to cause p gstrings to be converted correctly
Sometimes when you need more specific control the Sometimes when you need more specific control, the MarshalAs attribute can be handy
For example what would you do if one parameter needs to For example, what would you do if one parameter needs to be an ANSI string and another a Unicode string?
[ ll (" d ld i dll")][DllImport("GoodOldCFunctions.dll")]publicstaticexternbool IsTextAllInGreek(
[MarshalAs(UnmanagedType LPWStr)] stringtext);[MarshalAs(UnmanagedType.LPWStr)] stringtext);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Calling API FunctionsUnsafe Code and Interoperability 26C# 30
Calling API FunctionsTo call the f nction Beep e ported b To call the function Beep exported by Kernel32.dll, you would simply declare:y p y
[DllImport(kernel32.dll")]publicstaticexternint Beep(uint freq,uint duration);
For API functions that accept string p p( q, );
parameters, the considerations outlined earlier are relevantearlier are relevant However, an additional consideration must be taken
into accountinto account
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
The API A and W SuffixUnsafe Code and Interoperability 27C# 30
The API A and W SuffixAll Win32 API f nctions that contain string All Win32 API functions that contain string parameters are exported as two versionsp p
MessageBox is a macro that becomes: MessageBoxA for ANSI applications MessageBoxW for Unicode applications
In C/C++, a call to MessageBox is converted to one of the above by the preconverted to one of the above by the pre-processor based on the presence of a UNICODE pre-processor definition
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Choosing Between A and WUnsafe Code and Interoperability 28C# 30
Choosing Between A and WWhen declaring such a function in C# When declaring such a function in C#, we are allowed to use the generic nameg
publicstaticexternint MessageBox(uint hwnd,stringtext,stringcaption,uint type);
P/Invoke will call either MessageBoxA or uint hwnd,stringtext,stringcaption,uint type);
MessageBoxW based on this logic:DllImport CharSet value Function calledDllImport CharSet value Function calledCharSet.Ansi (default) MessageBoxACharSet.Unicode MessageBoxW
CharSet.Auto Platform Dependent
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
p
AttentionUnsafe Code and Interoperability 29C# 30
AttentionOn a Unicode based platform On a Unicode based platform: The Unicode string gets converted to an ANSI string This is passed to MessageBoxA which in turn calls MessageBoxExAg
MessageBoxExA converts the ANSI string into a Unicode string and passed to MessageBoxExWg p g
A bit wasteful, dont you think?
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
SolutionUnsafe Code and Interoperability 30C# 30
SolutionA better approach o ld be to se the A better approach would be to use the CharSet.Auto setting:g[DllImport("User32.Dll",CharSet=CharSet.Auto)]
publicstaticexternint MessageBox(
On a Unicode based platform:
publicstaticexternint MessageBox(uint hwnd,stringtext,stringcaption,uint type);
On a Unicode based platform: The C# Unicode string gets passed directly to
hi h i t llMessageBoxW which in turn calls MessageBoxExW
Thats it. The string is never convertedThat s it. The string is never converted CharSet.Auto is a good choice for Win32 API
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Other [DllImport] PropertiesUnsafe Code and Interoperability 31C# 30
Other [DllImport] PropertiesE tS lli If t t t tt t ill bExactSpelling If set to true, no attempt will be
made to add A or W when looking for the namelooking for the name.The default is false.
EntryPoint Specifies the name of the exported function in the DLL. This allows the C# class to declare the function with a different name.The default is to use the given name.
CallingConvention Specifies the calling convention.The default is StdCall
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
The default is StdCall.
Marshaling StructuresUnsafe Code and Interoperability 32C# 30
Marshaling StructuresIn C/C++ In C/C++ Structure and classes physical field layout is
determined by field order
In C#In C# Structure field layout is the same as in C/C++
C Class layout is determined by the compiler to gain better performance and memory usage
To control C# physical fields layout Use the StructLayout attribute Use the StructLayout attribute
LayoutKind.Sequential is the C/C++ layout
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Marshaling StructuresUnsafe Code and Interoperability 33C# 30
An API ExampleBOOLPtInRect(
CONSTRECT*lprc,//ApointertoaRECTstruct//POINTpt//APOINTstruct
);
The structures RECT and POINT are defined by the API as follows:
typedef struct {longleft;longtop;longright;longbottom;longleft;longtop;longright;longbottom;
}RECT;typedef struct {yp {
longx;longy;}POINT;
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Marshaling StructuresUnsafe Code and Interoperability 34C# 30
Marshaling Structures[StructLayout(LayoutKind.Sequential)]//Notreallyneededpublicstruct Point {
publicint x;publicint y;publicint y;
}[StructLayout(LayoutKind.Sequential)]//Notreallyneededpublicstruct Rect {
publicint left;publicint top;publicint top;publicint right;publicint bottom;
}
[DllImport("User32 dll")][DllImport( User32.dll )]publicstaticexternbool PtInRect(
refRect rect,Pointpoint);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Marshaling ClassesUnsafe Code and Interoperability 35C# 30
Marshaling Classes[StructLayout(LayoutKind.Sequential)]//Notreallyneededpublicstruct Point {
publicint x;publicint y;publicint y;
}[StructLayout(LayoutKind.Sequential)]//AmustpublicclassRect {
publicint left;publicint top;publicint top;publicint right;publicint bottom;
}
[DllImport("User32 dll")]//Rect isareferencetype[DllImport( User32.dll )]//Rect isareferencetypepublicstaticexternbool PtInRect(Rect rect,Pointpoint);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Using ref and outUnsafe Code and Interoperability 36C# 30
//extern"C"voidStatistics(doublenums[],int count,
Using ref and out
//double*pmean,double*pstddev);publicclassTest{
[DllImport("GoodOldCFunctions.dll")]publicstaticexternvoidStatistics(double[]nums,
i t t td bl td bl tdd )int count,outdoublemean,outdoublestddev);}double[]nums ={34.5,2.0,78.111,5,0.001};doublemean;//Themean(average)doublemean;//Themean(average)doublestddev;//Thestandarddeviation
Test.Statistics(nums,5,outmean,outstddev);Console.WriteLine("Mean:{0}StandardDeviation:{1}",
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
mean,stddev);
Using C# PointersUnsafe Code and Interoperability 37C# 30
Using C# Pointers//extern"C"voidStatistics(doublenums[],int count,// double*pmean,double*pstddev);publicclassTest{
[DllImport("GoodOldCFunctions.dll")]publicstaticexternunsafevoidStatistics(double*nums,
i t t td bl td bl tdd )int count,outdoublemean,outdoublestddev);}unsafe{unsafe{
fixed(double*pnums =nums){{
Test.Statistics(pnums,5,outmean,outstddev);Console.WriteLine("Mean:{0}Deviation:{1},( { } { } ,
mean,stddev);}
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
}
Retrieving StringsUnsafe Code and Interoperability 38C# 30
Retrieving Strings Many C functions return strings as output Many C functions return strings as output
They normally do this by having the caller pass in an uninitialized buffer of characters to be filled by theuninitialized buffer of characters to be filled by the function itselfAs a safety measure the caller is usually required to As a safety measure, the caller is usually required to pass in the length of the buffer
Consider this Win32 API: Consider this Win32 API:DWORDGetModuleFileName((
HMODULEhModule,//handletomoduleLPTSTRlpFilename,//filenameofmoduleDWORDnSize //sizeofbuffer
);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Retrieving StringsUnsafe Code and Interoperability 39C# 30
Retrieving StringsHo o ld s ch a f nction be called from How would such a function be called from C#? This turns out to be a special case since marshaling
is required between string types and the string isis required between string types and the string is being returned
Using a simple string variable wont work because itUsing a simple string variable won t work, because it is an immutable object
The a to handle s ch sit ations is b The way to handle such situations is by using an object of type StringBuilderg j yp g P/Invoke handles StringBuilder objects in a
special way specifically for this purpose
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
special way specifically for this purpose
Retrieving StringsUnsafe Code and Interoperability 40C# 30
Retrieving StringspublicclassTest{publicclassTest{
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]publicstaticexternuint GetModuleFileName(publicstaticexternuint GetModuleFileName(
uint hModule,StringBuilder filename,int nSize);}}//StringBuilder filename=newStringBuilder(500);g g ( );Test.GetModuleFileName(0,filename,filename.Capacity);
Console.WriteLine("Thefilenameofthecurrentmoduleis:{0}",filename);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Unsafe Code and Interoperability 41C# 30
Chapter 22 Exercise 1
CALLING A DLL FUNCTION
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Unsafe Code and Interoperability 42C# 30
Chapter 22 Exercise 2
CALLING WIN32 API
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
Chapter SummaryUnsafe Code and Interoperability 43C# 30
Chapter Summary C# can use pointers if the assembly is C# can use pointers if the assembly is
marked as unsafe Use the fixed keyword to get a pointer P/Invoke lets us call unmanaged functions P/Invoke lets us call unmanaged functions
from any .NET managed language P/Invoke knows to marshal parameters
There are times that we will give P/Invoke some hintsThere are times that we will give P/Invoke some hints To help it understand the correct prototype To gain performanceg p
These hints are passed using the [DllImport]attribute options or the [MarshalAs] attribute
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel