[ Reljam @ 21.06.2002. 21:51 ] @
U zavisnosti od toga sta radite, moze da se desi da vam zatreba da u C#-u radite sa C-olikim struktovima: primer toga bi bio slanje podataka na socket po nekom protokolu. Iz jednog ili drugog razloga sam skoro morao da implementiram deo Kerberos autentikacije u C#-u, tako da sam odlucio da iskoristim stvari koje sam naucio i da barem malo olaksam zivot drugima:

Problem je vrlo jednostavan:

Recimo da hocu ovo da uradim u Cu:

Code:

struct MYSTRUCT Data;
Data.a=3;
Data.b=5;
SendToSocket((char*) &Data);


Deluje jednostavno, zar ne? E sada, u C#-u nije dozvoljeno tako olako baratanje pointerima. Sto se toga tice, ni raspored polja u structu nije zagarantovan da ce ostati onakav kako ga vi specificirate. Da bi se tako nesto uradilo, potrebno je ovako definisati C# struct:

Code:

[StructLayout(LayoutKind.Sequential, Pack=1)]
protected struct MessageHeader 
{
    public ushort    type;
    public ushort    entry;
};


LayoutKind.Sequential oznacava da ovaj struct treba da postoji u memoriji u onom redosledu po kome su definisana polja, bas kao u C-u. Pack=1 pakuje podatke na 1 bajt, dakle radi istu stvar kao ta opcija u C-u.

Sledeci "trik" je definisati funkciju koja barata sa podatcima kao "unsafe" - to omogucuje koriscenje pravih pointera:

Code:

protected unsafe void FastHandler()
{


I sada nastupa zanimljiv deo - alocira se niz memorije, i onda se 'baci' pointer na njega, koji se kastuje u odgovarajuci tip podataka:

Code:

byte []outArray = new Byte[PACKET_SIZE];
fixed (byte *outBytes=outArray)
{
    MessageHeader    *AuthRep=(MessageHeader*) outBytes;
    AuthRep->type = 3;
    AuthRep->entry = 5;
}


fixed naredjuje Garbage Collectoru da fiksira lokaciju objekta outArray u memoriji i da je ne pomera dok se ne zavrse operacije sa pointerima.

Naravno ovo je samo mali primer, isti efekat bi mogao da se napravi i bez pointera, ali ono gde se ova metoda primenjuje je recimo unos podataka sa socketa i "kastovanje" tih podataka u odgovarajucu strukturu. U svakom slucaju, ova metoda moze da bude korisna kada zatreba neka manipulacija bajtova i structova...

Srecno sa radom!
[ Dragi Tata @ 22.06.2002. 06:19 ] @
Odličan tekstić.

Dodaću samo da kada imam posla sa Win32 API funkcijama ili drugim "native" kodom, najviše volim da komunikaciju sa time odradim uz pomoć MC++a, pa to upakujem u jednu komponentu koju posle lako zovem iz drugih .NET jezika. Nekako mi deluje "čistije", a i lakše.
[ Reljam @ 22.06.2002. 09:12 ] @
Tu si potpuno u pravu, to sam i ja hteo na pocetku da uradim. Medjutim, ispostavilo se da je bilo potrebno uraditi samo ovu jednu stvar sa structovima, tako da sam odlucio da to ipak bude na ovaj nacin. Da je bilo iole vise posla sa structovima uradio bih to u managed kodu. Ovo je bilo taman na nivou da se isplatilo ne komplikovati dodatno kod, mada moram da priznam da je stvarno lepa integracija managed i unmanaged koda.

A inace za one koji sumnjaju u brzinu C#-a, sa ovim moze da se napravi (ruku na srce vrlo jednostavan) kerberos 'emulator' koji servisira do 100 simultanih zahteva po procesoru (to je maks. koji sam probao), a na svaki kerb zahtev mora da se odgovori za manje od 200 msec. Procesori su na 1 GHz, dakle nista nerealno brzo. Za sve to vreme postoji dodatnih 100 threadova po procesoru koji rade nesto (uglavnom citaju i pisu po socketima). Zauzece procesora je oko 70%, i to sa debug buildom.

Sve u svemu, eto malo ulivanja poverenja u C# i .NET tehnologije ;)