Documente Academic
Documente Profesional
Documente Cultură
C# 3.0
Chapter 22 Unsafe Code and
Interoperability
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Interoperability Introduction
Interoperabilit
Interoperability is the ability
abilit to have
ha e
g code and unmanaged
g code work
managed
together in one application
Managed code is code that requires the execution
environment of the Common Language Runtime
Unmanaged
U
d code
d iis code
d th
thatt d
does nott need
d th
the CLR
Unmanaged code is outside the reach of the CLRs
management services
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
.NET
NET Interoperability Options
The .NET
NET pro
provides
ides uss with
ith three main
p
y options:
p
interoperability
Calling C DLL functions from a .NET component
This service is termed Platform
Platform Invoke
Invoke
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
.NET
NET Interoperability Services
The core interoperability services are
performed by the CLR
The .NET framework provides us with several
Interoperability APIs (attributes and helper classes)
System.Runtime.InteropServices
i
i
C# 30
C# provides
id references
f
References lead to safe code
They are guaranteed to refer to valid objects
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Th
The code
d will
ill only
l compile
il if th
the /unsafe
/
f
compiler
option
is specified
p
p
p
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Primitive types
Value types with no references (recursively)
Pointer Types (i.e., pointer to a pointer)
void *
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
C# 30
i i St i
df '&'
fixed(char*ps =s)
{
*ps ='Y';//Donttrythisathome!
}
}
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Platform Invoke
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Platform Invoke
Consider the following C function which
tests whether a number is prime:
int IsPrime(int num);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
C# 30
C# 30
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
C# 30
Type Mappings
C#
Type
float
System.Single
Yes
float
double System.Double
Yes
double
sbyte
System.SByte
Yes
signedchar
byte
System.Byte
Yes
unsignedchar
short
System.Int16
Yes
short
ushort System.UInt16
Yes
unsignedshort
int
System.Int32
Yes
int
uint
y
System.UInt32
Yes
unsignedint
g
long
System.Int64
Yes
__int64
ulong
System.UInt64
Yes
unsigned
int64
unsigned__int64
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Type Mappings
C# T
Type
Framework
F
k
Name
I
Isomorphic
hi Matching
M t hi C Type
T
bool
System Boolean
System.Boolean
No
int
char
System.Char
No
char or wchar_t
string
System Boolean
System.Boolean
No
char* or
wchar_t* (or BSTR
for COM))
object
System.Object
No
VARIANT (COM
interoperability
only)
1D-array of
i
isomorphic
hi
Yes
Array of equivalent
i
isomorphic
hi
Other arrays
No
Interface or
SAFEARRAY (COM)
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
String Conversions
Converting simple non
non-isomorphic
isomorphic types
like bool is an easy task for the runtime
There is a one-to-one mapping between these types
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
String Example
Consider the following
follo ing C ffunction
nction which
hich
counts the number of digits
g in a string:
g
int CountDigits(char*text);
The
Th corresponding
di C# d
declaration
l ti iis:
[
[DllImport("GoodOldCFunctions.dll")]
p
(
)]
publicstaticexternint CountDigits(stringtext);
What
Wh t should
h ld we do
d if the
th C function
f
ti
p
Unicode characters?
expected
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
DllImportAttribute Fields
The DllImportAttribute
DllImportAttrib te class has
properties
p
which can be used to
some p
override the default behavior
The property CharSet can be used to indicate how
strings should be passed
The
Th legal
l
l values
l
ffor thi
this property
t come from
f
the
th
CharSet enumeration which contains:
Ansi
A i (default)
(d f lt)
Unicode
Auto
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Using CharSet
ti expects
t aU
i d string:
ti
Thi
This C ffunction
Unicode
int IsTextAllInGreek(wchar_t*text);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
[DllImport(kernel32.dll")]
publicstaticexternint Beep(uint
p
p(
freq,uint
q,
duration);
);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
The API A
A and W
W Suffix
All Win32 API functions
f nctions that contain string
parameters are exported
p
p
as two versions
MessageBox is a macro that becomes:
MessageBoxA for ANSI applications
MessageBoxW for Unicode applications
C# 30
Choosing Between A
A and W
W
When declaring such a function in C#
C#,
name
we are allowed to use the generic
g
publicstaticexternint MessageBox(
uint hwnd,stringtext,stringcaption,uint type);
MessageBoxW
CharSet.Auto
Platform Dependent
p
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Attention
On a Unicode based platform:
platform
The Unicode string gets converted to an ANSI string
This is passed to MessageBoxA which in turn calls
g
MessageBoxExA
MessageBoxExA converts the ANSI string into a
Unicode string
g and p
passed to MessageBoxExW
g
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Solution
A better approach would
o ld be to use
se the
CharSet.Auto setting:
g
[DllImport("User32.Dll",CharSet=CharSet.Auto)]
publicstaticexternint MessageBox(
uint hwnd,stringtext,stringcaption,uint type);
That
Thats
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
C# 30
If sett tto t
true, no attempt
tt
t will
ill be
b
made to add A or W when
looking for the name
name.
The default is false.
EntryPoint
C# 30
Marshaling Structures
In C/C++
Structure and classes physical field layout is
determined by field order
In C#
Structure field layout is the same as in C/C++
Class
C
layout is determined by the compiler to gain
better performance and memory usage
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Marshaling Structures
An API Example
BOOLPtInRect(
CONSTRECT*lprc,//ApointertoaRECTstruct
POINTpt//APOINTstruct
//
);
C# 30
Marshaling Structures
[StructLayout(LayoutKind.Sequential)]//Notreallyneeded
publicstruct Point {
publicint x;
publicint y;
}
[StructLayout(LayoutKind.Sequential)]//Notreallyneeded
publicstruct Rect {
publicint left;
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
C# 30
Marshaling Classes
[StructLayout(LayoutKind.Sequential)]//Notreallyneeded
publicstruct Point {
publicint x;
publicint y;
}
[StructLayout(LayoutKind.Sequential)]//Amust
publicclassRect {
publicint left;
publicint top;
publicint right;
publicint bottom;
}
[DllImport("User32
dll")]//Rect
[DllImport(
User32.dll
)]//Rect isareferencetype
publicstaticexternbool PtInRect(Rect rect,Pointpoint);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Using ref
ref and out
out
//extern"C"voidStatistics(doublenums[],int count,
//double*pmean,double*pstddev);
publicclassTest{
[DllImport("GoodOldCFunctions.dll")]
publicstaticexternvoidStatistics(double[]nums,
i t count,outdoublemean,outdoublestddev);
int
t td bl
td bl tdd )
}
double[]nums ={34.5,2.0,78.111,5,0.001};
doublemean;//Themean(average)
doublestddev;//Thestandarddeviation
Test.Statistics(nums,5,outmean,outstddev);
Console.WriteLine("Mean:{0}StandardDeviation:{1}",
mean,stddev);
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Using C# Pointers
//extern"C"voidStatistics(doublenums[],int count,
//
double*pmean,double*pstddev);
publicclassTest{
[DllImport("GoodOldCFunctions.dll")]
publicstaticexternunsafevoidStatistics(double*nums,
i t count,outdoublemean,outdoublestddev);
int
t td bl
td bl tdd )
}
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
C# 30
Retrieving Strings
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 the
function itself
As a safety measure
measure, the caller is usually required to
pass in the length of the buffer
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Retrieving Strings
Ho
How would
o ld ssuch
ch a ffunction
nction be called from
C#?
This turns out to be a special case since marshaling
is required between string types and the string is
being returned
Using a simple string variable wont
won t work,
work because it
is an immutable object
The way
a to handle ssuch
ch sit
situations
ations is b
by
g an object
j
of type
yp StringBuilder
g
using
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
C# 30
Retrieving Strings
publicclassTest{
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
publicstaticexternuint GetModuleFileName(
uint hModule,StringBuilder filename,int nSize);
}
//
g
g
(
);
StringBuilder
filename=newStringBuilder(500);
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
C# 30
Chapter 22 Exercise 1
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Chapter 22 Exercise 2
Copyright SELA Software & Education Labs Ltd. 14-18 Baruch Hirsch St. Bnei Brak 51202 Israel
C# 30
Chapter Summary
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
from any .NET managed language
P/Invoke knows to marshal parameters
There are times that we will give P/Invoke some hints
To help it understand the correct prototype
To gain
g
performance
p