Feeds:
Posts
Comments

Archive for November, 2005

In India, vehicles are driven on the left side of the road, same as in the UK, while in Canada, vehicles are driven on the right side of the road. Now, in India, when crossing any road with 2-way traffic, you look to your right and then rush to the middle of the road if the lane is empty, then look to the left and run as fast as possible to the other side – pretty simple really. Now in Canada, as a pedestrian, my greatest psychological challenge is to overcome this subconscious tendency to look to my right when crossing the road – here, you need to do it the other way round, as in look to the left first, cross to the middle of the road, then look to the right and cross again. I hope I can get it sorted out before some vehicle knocks me down :hmmm:

Read Full Post »

The futility of const ref objects

Most C++ programmers would have trained themselves to use const objects and const member functions whenever and wherever possible, and rightly so. But, if you try to declare a const member function for a ref class, you’ll get error C3842 – member functions of managed types cannot be const. So, while you can declare a ref object to be const, you’d serve no purpose in doing so, because you won’t be able to invoke any methods on it, except by using const_cast to remove the const-ness of the object. I believe that the idea behind this was to be compatible with other CLI languages like C# which do not support const member functions. I am told that a future release of the compiler would allow managed member functions to be declared const but that this is not a high priority target as of now. So, this is one more difference when using C++ to do CLI programming compared to doing native programming.

Read Full Post »

When you compile with /clr and you have a native class in your code (one that’s neither a ref class nor a value class), there are two entry points generated for its methods – a managed entry point and a native entry point. This allows both managed and native callers to call these methods, and the native entry point acts as a thunk to the managed entry point. Virtual functions are always called through the native entry point. Now, this results in a performance issue; when a managed caller calls a virtual function in a /clr compiled native class, there are two managed-unmanaged transitions that are required – the first managed-to-native transition to invoke the native entry point and the second native-to-managed transition to invoke the managed entry point – this is referred to as double thunking.

class N
{
public:
    N()
    {
        Console::WriteLine(__FUNCSIG__);
    }
    N(const N&)
    {
        Console::WriteLine(__FUNCSIG__);
    }
    ~N()
    {
        Console::WriteLine(__FUNCSIG__);
    }
};

class X
{
public:
    virtual void UseNVirt(N)
    {
        Console::WriteLine(__FUNCSIG__);
    }

Now, if you call UseNVirt as follows, you can see the effect of double thunking :-

    X* x = new X();
    Console::WriteLine();

    x->UseNVirt(n);
    Console::WriteLine();

/*** Output

__thiscall N::N(const class N &)
__thiscall N::N(const class N &)
__thiscall N::~N(void)
void __thiscall X::UseNVirt(class N)
__thiscall N::~N(void)

***/

The solution to this is to use __clrcall appropriately :-

class X
{
public:
    virtual void UseNVirt(N)
    {
        Console::WriteLine(__FUNCSIG__);
    }
    virtual void __clrcall UseNVirtClrCall(N)
    {
        Console::WriteLine(__FUNCSIG__);
    }

Now, if you call UseNVirtClrCall as follows, there’s no double thunking involved :-

    X* x = new X();
    Console::WriteLine();

    x->UseNVirtClrCall(n);
    Console::WriteLine();

/*** Output

__thiscall N::N(const class N &)
void __clrcall X::UseNVirtClrCall(class N)
__thiscall N::~N(void)

***/

So, my suggestion to those who are doing mixed mode programming would be to profusely use __clrcall except when you know for certain that the method could be invoked by a native caller. Note that VC++ 2005 does some optimizations on its own and implicitly adds __clrcall to any method with a managed type in its signature (including the return type).

Read Full Post »

The __FUNCSIG__ macro

I cannot believe that I didn’t know of this macro all this while. Countless times in the past, when I had to track the life-cycle of an object, I had put code such as printf("inside ctor") and printf("inside function F(int)") in my class, and now I find out that all I had to use was the __FUNCSIG__ macro.

ref class R
{
public:
    R()
    {
        Console::WriteLine(__FUNCSIG__);
    }
    void Hello()
    {
        Console::WriteLine(__FUNCSIG__);
    }
    ~R()
    {
        Console::WriteLine(__FUNCSIG__);
    }
    int index;
};

//...

    R^ r = gcnew R();
    r->Hello();
    delete r;

/*** Output

__clrcall R::R(void)
void __clrcall R::Hello(void)
__clrcall R::~R(void)

***/

Other similar macros are __FUNCDNAME__ which returns the decorated name and __FUNCTION__ which returns the undecorated name (without the full signature). These are available in VC++ 2003 and 2005, but I am not sure if they existed in VC++ 6, so perhaps someone could confirm that.

Read Full Post »

Got a new desktop

I got a new P4 3.2 GHz with HT, 2 MB L2 Cache, 2 Gigs of RAM, 160 GB SATA, 17″ LCD, DVD burner etc. It’s my first ever LCD outside of my laptop and it’s a welcome change :-) I’ve installed XP Prof SP2, Office 2003, VS.NET 2003, VS.NET 2005 and the regular stuff like MSN Messenger, Google Toolbar etc. Installations were pretty fast in general and I didn’t have any trouble with getting the right driver for any device. Well, I am all set for some coding now :-D

Read Full Post »

Follow

Get every new post delivered to your Inbox.