M.E. BRING .NET CLR Support to C ++ Chinese version (Part 2)

zhaozj2021-02-16  50

Managed Extensions Bring .NET CLR Support To C Chinese version (Part 2)

Author: Chris Sells

Translator: glory

Hocked class and interface

When you use C hosted expansion compile, it is default that you will get the hosted code (it allows you to access managed types, not non-managed types). If you want your class being hosted, you need to use a new Managed C keyword: __ GC. Once you do this, and if you want your class to be used by the outside, you can use the keyword public. Table 3 shows an example of achieving your .NET class Talker in Managed C . You can compile this class like this:

CL / LD / CLR TALKER.CPP / O TALKER.DLL

Table 3 Managed C Talker

// Talker.cpp

#using

Using Namespace System;

Namespace MSDNMagsamples

{

PUBLIC __GC CLASS TALKER

{

PUBLIC:

String * something;

Void signomething () {console :: write;}

~ Talker () {Console :: WriteLine (S "~ Talker");}

}

}

There are three interesting things worth mentioning here. First, I add a parser to the category, or at least it looks. Remember that I said that the NET type does not really have an elevator and only one optional finalize method? Oh, because the C programmer is such habits to that mark, the Managed C team decides to map the Managed C designer to a Finalize's implementation and add a call to the base class Finalize method. The C # group is also dried, but remembers that there is no sectors in the traditional C sense in these two languages.

The second interesting thing is that I will expose public data members directly to .NET customers. In .NET, the data member is called a field, which means that they have no code data, and, as the public data member is a bad note, the field (the translation: refers to the public) for the .NET class. It is also a bad idea because they make you could make some calculations, verify, or set it to read-only. In C , you use the getter and setter functions to expose the data member. In .NET, you can use properties to achieve the same effect. The attribute is a function of exposing data, however, in some extent, allow you to add some code to the component. Managed C uses keyword __property and specifically indicating an attribute as a prefix as a prefix, as follows:

PUBLIC __GC CLASS TALKER

{

Private:

String * m_something;

PUBLIC:

__property string * get_something () {return m_something;}

__property void set_something (string * something) {m_something = Something;}

// ...

}

If you want to calculate the output or verification input, you can do it in the GET_ or SET_ function, respectively. Similarly, if you want to set the property to read-only or write, just remove the corresponding set_ or get_ function. The client, field, and attribute are the same: t-> Something = "Greetings Planet Earth";

However, be careful when switching between fields and attributes. As your design is justified, it seems that it is easy to start from the field and then transform to property. Unfortunately, the potential IL of field access and attribute access is different, so if you change a field to properties, the customer who originally used this field will trigger an exception. If you have changed, your customers must recompile.

Look at the Managed C Talker in Table 3, it can be noted that it is exposed to all .NET customers. This trick COM can't play. COM can only expose the function through the interface. The disclosure of the C class that implements a COM interface is not necessarily available - unless this method is part of the interface. .NET does not need to expose functions to interfaces respectively. However, when exposed to generalized functions, the interface is still important. In order to define a .NET interface in Managed C , you can use the keyword __gc with the keyword __gc, as follows:

PUBLIC __GC __INTERFACE ICANTALK

{

Void talk ();

}

Public __gc class talker: Public ICANTALK

{

// ...

// ICANTALK

Void talk () {saysomething ();

}

Since customers can access Talker classes, it can call the ICANTalk method as in the way of calling other disclosure. Or, if the customer has a reference to the base class (all managed types are finally derived from system :: object), it can be converted to this type. Managed C customers can convert through Dynamic_cast, it has been upgraded to support .NET type conversion, or use a converter called __TRY_CAST, if the conversion fails, it will throw an exception:

Void MakeTalk (Object * Obj)

{

Try

{

ICANTALK * CANTALK = __TRY_CAST (OBJ);

Cantalk-> talk ();

}

Catch (invalidcastexception *)

{

Console :: WriteLine (s "Can't Talk Right Now ...");

}

}

Mixed hosted and unmanaged code

When you set the files in the project to / CLR option, you will get the hosted code, which allows you to access the managed type. If you want to take your code snippered in unmanaged, you can use a new #pragma statement:

//Mixed.cpp

// ... default is a hosted code ...

#pragma unmanaged

// ... unmanaged code ...

#pragma managed

// ... hosted code ...

#pragma allows you to mix in the same module to mix managed and unmanaged code. Although not used by you, but you have to pay attention to some constraints (or even programmers using Visual Basic). Once you want to call the hosted code from the unmanaged code, if you try to pass the pointer to the hosted type, you must be careful.

For example, imagine that you want to call Vari4Fromi2, pass a hosted pile to the pointer to it, as follows: HRESULT __STDCALL VARI4FROMI2 (Short SiN, long * plout);

__gc struct shortlong

{

Short n;

Long L;

}

void main ()

{

Shortlong * sl = new shortlong;

SL-> n = 10;

Vari4Fromi2 (SL-> N, & SL-> L); // Compile time error

}

Fortunately, the compiler will prevent this behavior, because once you pass a hosted pointer into the unmanaged code, the garbage collector will lose the tracking of it, when the next time run, the garbage collector will easily move the pointer This object points to it.

To avoid this problem, you must explicitly secure the object in the scope, so that the garbage collector knows not to move this object. You can use keywords __pin to achieve this:

void main ()

{

Shortlong * sl = new shortlong;

SL-> n = 10;

Long __pin * pn = & sl-> L;

VARI4FROMI2 (SL-> N, PN);

}

Once this fixed variable has a scope, the lock on the memory that is hosted will be taken, the garbage collector can move it to remove it (the translation: the garbage collector will be moved in memory To remove, in order to reduce memory debris, effectively utilize memory, improve application efficiency, so the Move is not necessarily removed, destroyed. About the word Move on GC, more megadownload megadownload megadownload megadownload megadownload megadownload megadownload

Value type

To date, we have discussed the definition and use of the .NET reference type. The reference type is configured on the hosted pile and is destroyed by the garbage collector. On the other hand, .NET value type is a type configured on the stack (unless it is a member of a reference type) and is destroyed when the stack is released. The value type is used as a very simple combination type, which has not been burdered by the garbage collector. For example, in Managed C , a typical value type can be declared using keyword __value:

__Value struct Point

{

Point (long _x, long _y): x (_x), y (_y) {}

Long x;

Long Y;

}

Note that my Point value type has a constructor. Another constructor having all value types is the default constructor, which clears all members. For example, you can configure this value type in two ways:

Point Pt1; // (x, y) == (0, 0)

POINT PT2 (1, 2); // (x, y) == (1, 2)

Especially interesting is that the same processing value type is equivalent to processing reference types. This is useful, when you want to pass a value type to a method with reference type parameters, such as adding it to a collection. For example, in order to use WriteLine to output my value of X and Y, I may want to do this:

Console :: WriteLine (S "({0}, {1})", pt.x, pt.y);

Unfortunately, this is unable to compile because WriteLine needs a formatted string and a list of object references to System.Object. (WriteLine uses base class methods toString to request a printable string representation of an object). However, you can convert the value type to a reference type by packing. The packing action for a value type is to configure the corresponding reference type on the hosted pile and copy the value into new memory. In order to containe a value in Managed C , you can use operator __box: console :: writeline ({0}, {1}) ", __box (pt.x), __box (pt.y));

The value type is a way to create a simple, efficient type, while the box allows you to get a reference type of polymorphism when needed.

Tributes

If C is based on class, COM is based on the interface, then the core of .NET should be based on metadata. The different Managed C language features I showed in some way depends on metadata. However, Managed C does not expose a new keyword or compile indicator to provide access to all of these metadata (can be set on fittings or classes). In confession, it is not possible to do this, which makes a lot of space for variables and type names, especially since the metadata characteristics available are fully scalable.

In order to support the current and future metadata types, Managed C joins a new syntax: a feature block. The spectriological sentence block indicates to square brackets in front of the type to be characterized. For example, .NET supports something called an indexer, which is actually an array operation (in C and C #, in square brackets, representing brackets), operators overloaded managed equivalents. However, there is no __indexer keyword. Instead, Managed C requires that a feature is marked for this class to refer to the specified indexer:

[System :: Reflection :: Defaultmemberttribute (s "item")]

Public __gc class mycollection {__property string * GET_ITEM (int index);

The features we are discussing that defaultmembuttribute is actually a class defined in the System :: Reflection namespace, string "Item" is a constructor parameter, which indicates that the properties Item is the indexer of the class MyCollection.

In addition to setting features for class settings (also members), you can set features for accessories. For example, if you want to set a descriptive property on a fitting, you can do this:

Using Namespace Reflection;

[assmbly: assemblytitle (s "My MSDN Magazine Samples)];

In fact, the compiler team is so fascinated, they have added a lot of characteristics to let you wait .NET, you can write unmanaged code. For example, if you use the __interface keyword without using the __gc keyword, you will get a COM interface instead of the .NET interface. The new compiler also provides the same convenience for other ingredients, but you should keep in mind that these features are not .NET. They are only language maps to provide smoothing between C and COM and generate IDL and ATL code in the background. To learn more about C unmanaged extensions, see "C Attributes: make COM Programming a Breeze with New Feature In Visual Studio .NET". Where is we?

Unfortunately, although Managed C is so powerful and flexible, it is not .NET local language, which means books, articles, courses and code examples, etc. will not be written in Managed C , they will write with C # to write . But this is not very surprised, C has never become the local language on any popular platform. Unix and Win32 use c, Mac uses Pascal, Next uses Objective C (first), COM uses Visual Basic (Transplement: C programmer agrees? J), only Beos uses C as its local language, remember your last written beos Is the code time? The facts of .NET loves to C # is only means that another language will be translated into C equivalents, just as J. J. since 1983 Table 4 shows the list of C # main components, and also shows how they are mapped to the corresponding Managed C syntax.

Table 4 Managed C Rosetta Stone

Managed operation

C #

Managed C

Declare an interface

Interface iFoo {}

__gc __interface ifoo {};

Declare a class

Class foo {}

__GC class foo {};

Declare an attribute

INT x {get; set;}

__property int GET_X ();

__property void set_x (int x);

Implement an attribute

INT x {

Get {return m_x;}

Set {m_x = x;}

}

__property int GET_X () {return m_x;}

__property void set_x (int x) {m_x = x;}

Implement an interface

Class foo: ifoo {}

Class foo: public ifoo {};

Declare a commission

Delegate void callme ();

__dlegate void callme ();

Declare an indexer

String this [INDEX] {...}

[System :: Reflection :: Defaultmemberttribute

(S "item")]

__gc class mycollection {

__property string * get_item (int index);

}

Quote A accessory

/r:assembly.dll

#using

Introduced name space

Using system;

Using namespace system; object variable

Ifoo foo = new foo ();

Ifoo * pfoo = new foo ();

Member visit

Fuo.dofoo ();

Pfoo-> DOFOO ();

Quote a name space

System.console.writeline ("");

System :: Console :: WriteLine ("");

Declare an enumeration

ENUM FOO {bar, quux}

__Value enum foo {bar, quux};

Solutions when conflicting

Void iartist.draw () {...}

Void icowboy.draw () {...}

Void iArtist :: DRAW () {...}

Void iCowboy :: DRAW () {...}

Value type

Struct foo {...}

__Value struct foo {...};

Abstract type

Abstract Class foo {...}

__ABSTRACT CLOO {...};

Closed type

Sealed class foo {...}

__sealed class foo {...};

C-style conversion

Try {iFoo foo = (ifoo) bar;}

Catch (IllegialCastexception)

e) {...}

Try {iFoo * pfoo = __TRY_CAST (PBAR);

Catch (IllegialcastException * e)

{...}

Dynamic conversion

(Dynamic Cast)

Ifoo foo = bar as ifoo;

IF (foo! = Null) ...

Ifoo * pfoo = Dynamic_cast (PBAR);

IF (pfoo! = 0) ...

Type check

IF (bar is ifoo) ...

IF (Dynamic_cast (PBAR)! = 0) ...

Abnormal processing

Try {...}

Catch (myException e) {...}

Finally {...}

Try {...}

Catch (MyException * PE) {...}

__finally {...}

What is the location of these new features to put your existing code? The development of Managed C provides you with a gentle way to transplant your existing code into .NET. If you like to use the type of hosted, you have to do just a light-dial / CLR switch and recompile it. The code you exist will continue to work as you want, including your ATL and MFC projects.

Maybe you like to hosted in the .NET framework, maybe you like to use something yourself or your group created with C # or Visual Basic, no matter which kind of #using. Maybe you want to expose the existing C type hosted packaging, just like your packaging for Making COM, if so, public __gc will make you think.

In fact, Microsoft has made a surprising work that allows you to mix managed and unmanaged types and code in Managed C , and let you decide which code, when, ported to .NET.

- Full text -

转载请注明原文地址:https://www.9cbs.com/read-27817.html

New Post(0)