.NET

basiliskcanoeSoftware and s/w Development

Nov 2, 2013 (3 years and 9 months ago)

106 views

.NET

A Case Study for Interoperability

What is .NET ?



A set of technologies for developing and using components to create:


Windows Applications


Web Forms


Web Services


Supports the software lifecycle


Development


Debugging


Deployment


Maintenance




“[…] like the Solar System, .NET is huge. And it’s complex. And it’s
filled with black holes and other things that don’t always make
sense. Yet it turns out to be a fantastic system in which to develop
software applications.”


[Tim Patrick, An Introduction to .NET for Beginners]


This course’s goal with .NET: a case study for language interoperability

Microsoft .NET Framework
Architecture Overview


.NET: new runtime environment and comprehensive base class
library (FCL


Framework Class Library)



.NET
-
aware programming languages (C#, J#, VB, C++)

Common Language Specification

Base Class Library

Common Language Runtime

Operating System

Base Class Library Overwiev


The .NET framework class library supplies a standard set of classes,
interfaces, and structures for any language targeting .NET CLR =>
simplifies multi
-
language development, effectively providing a
common language API


Organized by namespaces.


A namespace consists of many classes and sub
-
namespaces.


General namespaces: the root namespace in the class library is the
System namespace, which contains many basic classes such as
Object, Console, and contains general sub
-
Namespaces such as IO,
Net, Remoting, etc.


Application specific namespaces: define types that are used for
building specific application types: System.Web.Services,
System.Web.UI, System.Windows.Forms


In order to use classes in a namespace a directive as
using
<namespace>

or
import <namespace>

must be included at the
beginning of code.



Some of the General Namespaces
from the Class Library

Namespace

Description

System

All the basic types used by every application

System.Collections

Types for managing collections of objects; includes the popular
collection types, such as stacks, queues, hash tables, and so on

System.IO

Types for doing stream I/O, walking directories and files

System.NET

Types for network communication

System.Reflection

Types that allow the inspection of metadata and late binding to
types and their members

System.Runtime.Remoting

Types that allow for types to be accessed remotely

System.Runtime.Serialization

Types that allow for instances of objects to be persisted and
regenerated from a Stream

System.Security

Types used for protecting data and resources

System.Threading

Types used for asynchronous operations and synchronizing
access to resources

Example: Using FCL in C#

// compile with csc ex1.cs


using System;

using System.Collections
;


public class Program {



public static void Main() {


ArrayList

myAL = new ArrayList();


myAL.Add( "one" );


myAL.Add( "two" );


myAL.Add( "three" );




Console.WriteLine
( "myAL has {0} elements.", myAL.Count );


}

}

Example: Using FCL in J#

//compile with vjc ex1.jsl


import System.*;

import System.Collections.*;


public class Program

{


public static void main(String[] args)


{



ArrayList
myAL = new ArrayList();



myAL.Add("one");



myAL.Add("two");



myAL.Add("three");




Console.WriteLine
("myAL has {0} elements.",






(Int32) myAL.get_Count());


}

}

Example: Using FCL in CPP

//compile with cl
/clr

ex1.cpp


using namespace System;

using namespace System::Collections;


int main()

{


ArrayList

myAL = gcnew ArrayList();


myAL.Add("one");


myAL.Add("two");


myAL.Add("three");



Console::WriteLine
( "{0}",myAL.Count );


}


This courses goals with .NET


A case study for interoperability: How
does .NET Architecture support
Interoperability



Interoperability problem


Problem: Developer wants to write different modules of
an application in different languages


Other solutions:


Representation standards & Communication protocols: address
the issues of passing data types between different machines.
Data can be passed by inter process communication
mechanisms


Using a language neutral Interface Description Language
-

CORBA. Objects can call methods across language and process
boundaries.


Binary standard: interoperability is assured at binary level


standardized calling model
-

COM


Disadvantages:


Permits only simple communication, no implementation inheritance
between classes written in different languages


Developer has to do special actions for interop (interface
descriptions)



Characteristics of the .NET solution
for interoperability


Consists of:


Common Type System and Common Language Specification
: defines common types
and common features that have to be provided by all participating languages


Metadata:

defines an uniform mechanism for storing and retrieving type information:
Compilers store type information as metadata, and the common language runtime uses this
information to provide services during execution;


MSIL: Intermediate Language
: all code is compiled to MSIL, which is a high
-
level machine
code executed by the runtime


CLR
: runtime can manage the execution of multilanguage applications because all type
information is stored and retrieved in the same way, regardless of the language the code was
written in.



.NET managed code benefits from the runtime's support for language interoperability
in the following ways:


Types can
inherit implementation

from other types, pass
objects as arguments

to another
type's methods, and
call methods

defined on other types, regardless of the language the
types are implemented in.


Debuggers, profilers, or other
tools are required to understand only one environment


the Microsoft intermediate language (MSIL) and metadata for the common language
runtime

and they can support any programming language that targets the runtime.



Bottom line: What about interoperability of .NET managed code with
unmanaged code ?


[MSDN: .NET Framework Developer's Guide: Language Interoperability Overview ]

Outline


Common Language Runtime


Managed Modules and Metadata


Assemblies


The Common Type System


The Common Language Specification


Examples of supported Multi
-
language
interoperability


Interoperability with Unmanaged Code


CLR


A runtime usable by different programming languages


CLR executes MSIL
-

it has no idea which language was used
for the source code


The features of the CLR are available to any and all
languages that target it


Features supported by CLR:


Just
-
in
-
time (JIT) compilers


JIT compiles intermediary language (MSIL) into native code


Common Type System


Garbage collector


Permission and policy
-
based security


Exceptions


Threading


Reflection



Managed modules


Compilers that target the CLR produce Managed modules


Managed module: a standard Windows portable executable (PE) file that requires
the CLR to execute


End
-
users must have the CLR installed on their machine in order to execute any managed
modules


A managed module consists of MSIL code and metadata

[Richter]


fig.1.1

Parts of a Managed module

[Richter]


Table 1.1

PE header

The standard Windows PE file header.

Indicates the type of file: GUI
-
EXE, CUI
-
EXE, or DLL. Has a timestamp indicating
when the file was built.

For modules that contain only IL code, the bulk of the information in the PE header
is ignored. For modules that contain native CPU code, this header contains
information about the native CPU code.

CLR header

Contains the information (interpreted by the CLR and utilities) that makes this a
managed module. The header includes the version of the CLR required, some
flags, the MethodDef metadata token of the managed module’s entry point method
(
Main
method), and the location/size of the module’s metadata, resources, strong
name,etc.

Metadata

Every managed module contains metadata tables. There are two main types of
tables: tables that describe the types and members
defined in your source code

and tables that describe the types and members
referenced by your source
code
.

Conceptually metadata are a superset of IDL’s, but, unlike them, are embedded
with the code.

IL code

IL (Intermediate Language) Code that the compiler produced as it compiled the
source code. The CLR later compiles the IL into native CPU instructions

IL is a CPU
-
independent machine language. IL is much higher level than most
CPU machine languages: IL understands object types and has instructions that
create and initialize objects, call virtual methods on objects, and manipulate array
elements directly.

Uses of metadata


Metadata makes a module self
-
describing


IntelliSense parses metadata to tell you what methods a
type offers and what parameters that method expects.


The CLR’s code verification process uses metadata to
ensure that your code performs only “safe” operations.


Metadata allows an object’s fields to be serialized into a
memory block, remoted to another machine, and then
deserialized, re
-
creating the object and its state on the
remote machine.


Metadata allows the garbage collector to track the
lifetime of objects. For any object, the garbage collector
can determine the type of the object and, from the
metadata, know which fields within that object refer to
other objects.


An assembly is a logical grouping of one or
more managed modules and resource files.


Single
-
file or multifile assemblies


An assembly is the logical unit of deployment,
and the smallest unit of reuse, security, and
versioning


CLR works with assemblies rather than managed
modules


Each Assembly is defined by a
Manifest:


Metadata that describes the assembly (version,
contained files, resource files, dependencies, etc.)

Assemblies

Assemblies

[Richter]


fig.1.2

Assemblies Manifest Contents


Manifest contains:


Identity information


Name, version number, culture, strong name


List of files in the assembly


Map of assembly types to files


Dependencies


Other assemblies used by this assembly


Exported types


Security permissions needed to run


Module Metadata Contents


Each module metadata contains:


Description of types


Name, visibility, base class, interfaces
implemented


Members (methods, fields, properties, events,

nested types)


Custom attributes


User
-
defined


Compiler
-
defined


Framework
-
defined


How to create an assembly


Single
-
file assemblies
: created with usual compiler
options


The C# (csc) and J# (vjc) compilers produce an
assembly when you specify any of the following
command
-
line switches:
/t[arget]:exe
,
/t[arget]:winexe
,
or
/t[arget]:library
. All these switches cause the
compiler to generate a single PE file that contains the
manifest metadata tables. The resulting file is either a
CUI executable, a GUI executable, or a DLL,
respectively.


The C++ compiler can produce managed or unmanaged
code. In order to produce managed code (an assembly)
use the
/CLR

switch


Example

//
File
Prog1.cs


using System;

public class Program {


public static void Main() {


Console.WriteLine( "Hi" );


}

}



Compile with: csc /t:exe Prog1.cs


Produces file Prog1.exe, that is a standard PE file of type Windows console
application


Prog1.exe is a single
-
file assembly (contains only one module)



You can (and usually do so) generate a
single
-
file assembly

from
multiple files of
source
-
code:



csc /target:library /out:lib.dll *.cs



Multifile assemblies refer to assemblies consisting of several
IL modules (nothing
to do with the number of source files !)
=> later





IL Disassembler: ILDASM.EXE


Allows you to inspect the metadata and disassembled IL code from
an assembly


Example: ILDASM on Prog1.exe

Example: MSIL code for
Program::Main

Example: Metadata for Prog1.exe


TypeDef:


Specifies the types defined here: Program


Type Program has 2 methods: Main and .ctor


TypeRef:


Specifies the types referenced by the module
-

these can be implemented in the same
module (TypeRef), in another module
(ModuleRef) of the same assembly or in
another assembly (AssemblyRef)

Example: Manifest for Prog1.exe

Multifile assemblies


[Richter] identifies 3 reasons to use multifile assemblies:


You can partition your types among separate files, allowing for
files to be incrementally downloaded
. Partitioning the types into
separate files also allows for partial or piecemeal packaging and
deployment for “shrinkwrapped” scenarios.


You can add resource or data files to your assembly
. For example,
you could have a type that calculates some insurance information. This
type might require access to some actuarial tables to make its
computations. Instead of embedding the actuarial tables in your source
code, you could use a tool (such as the assembly linker (AL.exe),
discussed later) so that the data file is considered to be part of the
assembly. By the way, this data file can be in any format


You can create assemblies consisting of types implemented in
different programming languages
. When you compile C# source
code, the compiler produces a module. When you compile Visual Basic
source code, the compiler produces a separate module. You can
implement some types in C#, some types in Visual Basic, and other
types in other languages. You can then use a tool to combine all these
modules into a single assembly. To developers using the assembly, the
assembly just contains a bunch of types; developers won’t even know
that different programming languages were used.


How to create a multifile assembly


Important:
The Visual Studio .NET IDE doesn’t natively support the ability
for you to create
multifile

assemblies. If you want to create multifile
assemblies, you must resort to using command
-
line tools.


Generating a module:


C# and J# compilers:
/t[arget]:module



C++ compiler:
/CLR:NOASSEMBLY /LD



This switch tells the compiler to produce a PE file that doesn’t contain the
manifest metadata tables. The PE file produced is always a DLL PE file, and this
file must be added to an assembly before the types within it can be accessed


Adding a module to an assembly: C# compiler supports the
/addmodule:module

switch


Creating an assembly from several modules: Assembly linker tool AL:


al /out:assembly /t:type netmodule1 netmodule2 …


Adding a resource file to an assembly:


al /embed [resource]


al /link [resource]


Example:


we have 2 source code files: RarelyUsedTypes.cs and FrecventlyUsedTypes.cs
and want to build a 2
-
modules assembly

Multifile Assembly Example (v1)


Generating a multifile assembly consisting of 2 managed modules, one with a manifest:

csc /t:module RUT.cs

csc /out:JeffTypes.dll /t:library /addmodule:RUT.netmodule FUT.cs

[Richter


Fig. 2
-
1]

Multifile Assembly Example (v2)


Generating a multifile assembly consisting of 3 managed modules, one with a manifest:

csc /t:module RUT.cs

csc /t:module FUT.cs

al /out:JeffTypes.dll /t:library FUT.netmodule RUT.netmodule

[Richter


Fig. 2
-
3]

Assembly Version Resource
Information


When AL or a compiler
produces a PE file assembly, it
also embeds a default
standard Win32 Version
resource


It can be examined by viewing
the file’s properties


=> Example: Version tab of the
Prog1.exe Properties dialog
box


Setting Version Information


The version resource fields
can be set using custom
attributes
applied at the
assembly level in the source
code


using System.Reflection;


[assembly:AssemblyCompany("Trei Biti SRL")]

[assembly:AssemblyCopyright("Copyright (c) 2008 Programatorul Iscusit")]

[assembly:AssemblyProduct("Program exemplu curs PASSC")]

[assembly:AssemblyInformationalVersion("2.0.0.0")]

[assembly:AssemblyFileVersion("1.0.0.0")]

[assembly:AssemblyVersion("3.0.0.0")]

Deployment of Assemblies


Two kinds of assemblies:


Privately deployed assemblies:


Are used by a single application


Reside in the application directory (or in a place explicitly configured
in the application)


Can be simply installed (copied) and uninstalled


Shared assemblies:


Are accessible to multiple applications


Located at
c:
\
winnt
\
assembly


Add assemblies by


Installer program


gacutil.exe



Shared Assemblies must have a “strong name”:


Guarantees name uniqueness (two different producers could write a
library with the same name)


Protect version lineage

»
No one else can create a new version of your assembly


a strongly named assembly is signed with a publisher’s public/private
key pair that uniquely identifies the assembly’s publisher.


Conclusion on Assemblies


An assembly is a
unit of reuse, versioning, and security
.


It allows you to partition your types and resources into separate files
so that you and consumers of your assembly get to determine which
files to package together and deploy.


Once the CLR loads the file containing the manifest, it can
determine which of the assembly’s other files contain the types and
resources that the application is referencing.


Assemblies are
self
-
describing
: Anyone consuming the assembly
is required to know only the name of the file containing the
manifest; the file partitioning is then abstracted away from the
consumer and may change in the future without breaking the
application’s behavior.


An application consists of one or more assemblies: this assures the
needed
technical infrastructure

(metadata, MSIL) for language
interoperability


Example:


MyClassInCsharp


MyProgramInJsharp


Example:


J# program uses C# class

//compile with

// vjc /r:MyClassInCsharp.dll
MyProgramInJsharp.jsl



Import System.*;


public class MyClassInJsharp
extends
MyClassInCsharp

{


public void doSomethingSpecial() {



doSomething(999);


}

}


public class MyProgramInJsharp {


public static void main(String[] args) {


MyClassInCsharp c=new MyClassInCsharp();


c.doSomething(5);


MyClassInJsharp j=new MyClassInJsharp();


j.doSomethingSpecial();


}

}


// compile with

// csc /t:library MyClassInCsharp.cs

// produces MyClassInCsharp.dll




using System;


public class
MyClassInCsharp

{


public void doSomething(int x) {


Console.WriteLine("doSomething on {0}", x);


}



}

C#

J#


Common Type System (CTS)


Defines what language features are supported by the CLR:
superset of the data types used by most modern programming
languages


Common Language Specification (CLS)


Defines what language features are essential to be implemented
by languages that want to produce code guaranteed to
interoperate with other languages. A subset of CTS that allows
code written in different languages to interoperate.


What languages?


Microsoft: C#, C++, Visual Basic, J#, JScript


Third
-
Party: Cobol, Eiffel, Smalltalk, Scheme, Oberon, Haskell,
Python, Perl, …

Interoperability

Cross Language

[Richter]


fig.1.6

Common Type System


CTS is a formal specification that describes how types are defined and how
they behave.


CTS establishes several rules regarding following issues:


What kind of members can a type contain


Type visibility and access to the members of a type.


Type inheritance, virtual functions


Object lifetime


All types must (ultimately) inherit from a predefined type:
System.Object
. This
Object
is the root of all other types and therefore guarantees every type instance
has a minimum set of behaviors.



These rules have been designed to accommodate the semantics
expressible in modern
-
day programming languages.


In fact, developers don’t need to learn the CTS rules per se since the
language they choose will expose its own language syntax and type rules
and will map the language
-
specific syntax into the “language” of the CLR
when it emits the managed module.


CTS rules are more important for language and compiler developers



CTS: Type members


The CTS specification states that
a type can contain zero or more
members, that can be
:


Field
A data variable that is part of the object’s state. Fields are
identified by their name and type.


Method
A function that performs an operation on the object, often
changing the object’s state. Methods have a name, a signature, and
modifiers. The signature specifies the calling convention, the number of
parameters (and their sequence), the types of the parameters, and the
type of value returned by the method.


Property
To the caller, this member looks like a field. But to the type
implementer, looks like a method (or two). Properties allow an
implementer to validate input parameters and object state before
accessing the value and/or calculate a value only when necessary.
They also allow a user of the type to have simplified syntax. Finally,
properties allow you to create read
-
only or write
-
only “fields.”


Event
An event allows a notification mechanism between an object and
other interested objects. For example, a button could offer an event that
notifies other objects when the button is clicked

CTS: Type visibility and access to
members


The CTS also specifies the rules for type visibility and for access to the
members of a type.


The CTS establishes the rules by which assemblies form a boundary of
visibility for a type, and the CLR enforces the visibility rules.


The valid options for controlling access to a method or a field:


Private
The method is callable only by other methods in the same class type.


Family
The method is callable by derived types, regardless of whether they are
within the same assembly. Note that many languages (such as C++ and C#)
refer to family as
protected
.


Family and assembly
The method is callable by derived types, but only if the
derived type is defined in the same assembly. Many languages (such as C# and
Visual Basic) don’t offer this access control. Of course, IL Assembly language
makes it available.


Assembly
The method is callable by any code in the same assembly. Many
languages refer to
assembly
as
internal
.


Family or assembly
The method is callable by derived types in any assembly.
The method is also callable by any types in the same assembly. C# refers to
family or assembly
as
protected internal
.


Public
The method is callable by any code in any assembly.

CTS: System.Object


Here’s another CTS rule: All types must ultimately inherit
from a predefined type:
System.Object
.


System.Object
is the root of all other types and
therefore guarantees every type instance has a minimum
set of behaviors.


Specifically, the
System.Object
type allows you to do
the following:


Compare two instances for equality



Obtain a hash code for the instance



Query the true type of an instance



Perform a shallow (bitwise) copy of the instance



Obtain a string representation of the instance’s object’s current
state


Common Language Specification


CLS is a subset of CTS


A component that uses only CLS features in the API that it
exposes to other code (including derived classes) is
guaranteed to be accessible from any programming language
that supports the CLS.


Components that adhere to the CLS rules and use only the
features included in the CLS are said to be CLS
-
compliant
components.


Why do we need CLS, besides CTS ?


CTS is too large to be integrally supported by all languages: the
CLS was designed to be large enough to include the language
constructs that are commonly needed by developers, yet small
enough that most languages are able to support it.


In addition, any language construct that makes it impossible to
rapidly verify the type safety of code was excluded from the CLS
so that all CLS
-
compliant languages can produce verifiable code if
they choose to do so.


Some of the CLS Rules


CLS rules apply only to those parts of a type that are exposed
outside the defining assembly.


For two identifiers to be considered distinct, they must differ by more
than just their case.


The .NET Framework class library includes types that correspond to
the primitive data types that compilers use. Of these types, the
following are CLS
-
compliant:
Byte
,
Int16
,
Int32
,
Int64
,
Single
,
Double
,
Boolean
,
Char
,
Decimal
,
IntPtr
, and
String
.


Methods are allowed to be overloaded only based on the number
and types of their parameters. Operator overloading is not in the
CLS.


The only calling convention supported by the CLS is the standard
managed calling convention; variable length argument lists are not
allowed


CLSCompliant Attribute


Assemblies explicitly indicate CLS compliance with
CLSCompliantAttribute
.


[assembly:CLSCompliant(true)]


This setting will generate warnings at compilation if the
assembly contains non
-
CLS
-
compliant code


Example:

J# program uses C# class

//compile with

// vjc /r:MyClassInCsharp.dll
MyProgramInJsharp.jsl



Import System.*;


public class MyClassInJsharp
extends
MyClassInCsharp

{


public void doSomethingSpecial() {



doSomething(999);


}

}


public class MyProgramInJsharp {


public static void main(String[] args) {


MyClassInCsharp c=new MyClassInCsharp();


c.doSomething(5);


MyClassInJsharp j=new MyClassInJsharp();


j.doSomethingSpecial();


}

}


// compile with

// csc /t:library MyClassInCsharp.cs

// produces MyClassInCsharp.dll


[assembly: CLSCompliant(true)];


using System;


public class
MyClassInCsharp

{


public void doSomething(int x) {


Console.WriteLine("doSomething on {0}", x);


}



}

C#

J#

A module that will be
consumed in another language
must be CLSCompliant.

The consumer module doesn’t
has to be CLSCompliant.

Example:

J# program uses C# class

//compile with

// vjc /r:MyClassInCsharp.dll MyProgramInJsharp.jsl



Import System.*;


public class MyClassInJsharp
extends
MyClassInCsharp

{


public void doSomethi ngSpecial() {



doSomethi ng(999);


}


public void dosomethingspecial() {



doSomething(111);


}



}


public class MyProgramInJsharp {


public static void main(String[] args) {


MyClassInCsharp c=new MyClassInCsharp();


c.doSomething(5);


MyClassInJsharp j=new MyClassInJsharp();


j.doSomethingSpecial();


}

}


// compile with

// csc /t:library MyClassInCsharp.cs

// produces MyClassInCsharp.dll


[assembly: CLSCompliant(true)];


using System;


public class
MyClassInCsharp

{


public void doSomething(int x) {


Console.WriteLine("doSomething on {0}", x);


}



}

C#

J#

Type MyClassInJsharp is now Non
-
CLSCompliant because it has 2
members with the same name and
signature (name case doesen’t matter).

Adding Non
-
CLSCompliant code
to the consumer module is OK !

MyProgramInJsharp works

Example:

Defining a CLS
-
Compliant class in C++

// compile with

// cl /CLR:safe /LD MyClassInCpp.cpp

// produces MyClassInCpp.dll


using namespace System;


[assembly: CLSCompliant(true)];


public ref class
MyClassInCpp

{


public:


void doSomething (int x);

};



void
MyClassInCpp::doSomething

(int x) {


Console::WriteLine("CPP: do Something on
{0}", x);

}

C++

A CLSCompliant
module in C++

A managed class
(C++ can support both
managed and
unmanaged types)

The Visual C
compiler can
generate managed
or native code
(default)

Example:


J# program uses C# and C++ classes

//compile with

// vjc /r:MyClassInCsharp.dll


// /r:MyClassInCpp.dll

//
MyProgramInJsharp.jsl


Import System.*;


public class MyClassInJsharp
extends MyClassInCsharp

{


public void doSomethingSpecial() {



doSomething(999);


}

}


public class MyProgramInJsharp {


public static void main(String[] args) {


MyClassInCsharp c=new MyClassInCsharp();


c.doSomething(5);


MyClassInJsharp j=new MyClassInJsharp();


j.doSomethingSpecial();


MyClassInCpp cpp=new MyClassInCpp();


cpp.doSomething(77);


}

}


J#



MyClassInC
pp
.dll



C++



MyClassInC
sharp
.dll



C#

Example:


C++ program uses C# and C++ classes


// compile with

//
cl /CLR MyProgramInCpp.cpp


#using <MyClassInCpp.dll>

#using <MyClassInCsharp.dll>


public ref class MySpecial:
MyClassInCsharp

{


public: void doSpecial();

};

void MySpecial::doSpecial() {


doSomething(777);

}


void main(void) {


MyClassInCpp cpp;


cpp.doSomething(56);


MyClassInCsharp c;


c.doSomething(99);


MySpecial s;


s.doSpecial();


}

C++



MyClassInC
pp
.dll



C++



MyClassInC
sharp
.dll



C#

.NET Generics across languages


Generics authored in one .NET language may be used in other .NET
languages.


Only some languages on the .NET Framework platform provide
support for authoring generic types and methods.


J# does not support authoring of generic collection classes, but it
does extend the Java
-
language syntax to provide support for using
specializations of generic types and methods defined in other .NET
Framework languages.


Example: a generic is defined in C# and consumed in J#.


The C# code defines a type parameter T which is unknown in the
compiled assembly. The J# code supplies a type argument to the
generic, thus generating a constructor where all unknown type
parameters have been replaced by actual types.

[MSDN Library: Generics in J#]

Example:


J# program consumes C# Generic Class





//compile with

// vjc /r:MyGeneric.dll GenericConsumer.jsl


public class MyClass {


public int x;

}


public class app

{


public static void main(String [] args)


{


MyGeneric<int> g1 =



new MyGeneric<int>();


MyGeneric<MyClass> g2 =



new MyGeneric<MyClass>();


}

}






// compile with

// csc /t:library MyGeneric.cs

// produces MyGeneric.dll


public class MyGeneric<T>

{


public T Field;

}




C#

J#

Interoperability

Managed/Unmanaged


.NET provides interoperability mechanism
to permit managed code to call into
unmanaged code and vice versa


Why?


Existing code works, why rewrite it?


Calling Microsoft functionality not yet available
as .NET assemblies


Calling 3
rd

party native code


Migrate your code incrementally

Interoperability

Managed/Unmanaged


Three complementary technologies enable these
managed/unmanaged interactions:


P
latform Invoke

(sometimes referred to as P/Invoke) enables
calling any function in any unmanaged language as long as its
signature is redeclared in managed source code.


COM i
nterop

enables calling into COM components in any
managed language in a manner similar to using normal
managed components, and vice versa. COM interop is
comprised of core services provided by the CLR, plus some
tools and APIs in the System.Runtime.InteropServices
namespace.


C++ interop

(sometimes referred to as It Just Works (IJW)) is a
C++
-
specific feature, which enables flat APIs to be used directly,
as they have always been used.


[MSDN Library: An Overview of Managed/Unmanaged Code Interoperability ]

Platform Invoke


When platform invoke calls an unmanaged function, it performs the
following sequence of actions:


Locates the DLL containing the function.


Loads the DLL into memory.


Locates the address of the function in memory and pushes its arguments onto
the stack, marshaling data as required.


Transfers control to the unmanaged function.

[MSDN Library]

Calling a DLL Export Directly from C#


To declare a method as having an implementation from a DLL
export, do the following:


Declare the method with the
static

and
extern

C# keywords.


Attach the
DllImport

attribute to the method. The
DllImport

attribute
allows you to specify the name of the DLL that contains the method.
The common practice is to name the C# method the same as the
exported method, but you can also use a different name for the C#
method, specifying the EntryPoint.


using System;

using System.Runtime.InteropServices;


class PlatformInvokeTest {


[DllImport("msvcrt.dll")]


public static extern int
puts
(string c);




public static void Main() {


puts
("Test");


}

}


[MSDN Library: Platform Invoke Tutorial ]

Default Marshaling and Specifying Custom Marshaling
for Parameters to Unmanaged Methods



When calling an unmanaged function from C# code, the common
language runtime must marshal the parameters and return values.


For every .NET Framework type there is a default unmanaged type,
which the common language runtime will use to marshal data across
a managed to unmanaged function call.


For example, the default marshaling for C# string values is to the
type LPTSTR (pointer to TCHAR char buffer). You can override the
default marshaling using the MarshalAs attribute in the C#
declaration of the unmanaged function.


[DllImport("msvcrt.dll")]

public static extern int puts(


[MarshalAs(UnmanagedType.LPStr)] string m);


C++ Interop


The Visual C++ compiler (cl) can generate IL code or
native code


Using compile switch /CLR it generates IL code from old
C++ source files


Although the IL code produced is managed, the data is
not: data objects that are not explicitly defined as
managed types have no metadata associated, are not
allocated from the managed heap and are not garbage
collected.


A C++ program can use both managed and unmanaged
types (IJW
-

It Just Works)


Example: A program that calls the standard C library function
printf (unmanaged code) and the System.Console.WriteLine
method (managed code).

C++ Interop Example

// compile with cl /CLR CppInterop.cpp


#include <stdio.h> // For printf


using namespace System; // For System namespace types


// Implement a normal C/C++ main function

void main() {


// Call the C runtime library’s printf function.


printf("Displayed by printf.
\
r
\
n");



// Call the FCL’s System.Console’s WriteLine method.


Console::WriteLine("Displayed by Console::WriteLine.");

}