Feeds:
Posts
Comments

Archive for April, 2004

I spent most of today afternoon/evening writing my first C++/CLI article for CodeProject. You can read it here – A first look at C++/CLI. The article covers the problems with the old syntax, how the new syntax solves these problems, how handles differ from pointers, declaring and using CLR types with the new syntax and boxing/unboxing. I have been meaning to write this article for the past few weeks, but wanted to get my facts right about boxing/unboxing before I ventured to do so.

Read Full Post »

The code snippets are now colorized – as you must surely have observed by now. Jambo Johnson took the WordPress colorizer and made the required changes for it to work with C++/CLI, and though we had a little problem with its unexpected indentation effects, a lucky guess helped solve that problem too.

I’ve also broken up my blog entries into categories now, which meant that some of the entries must have shown up as new in your RSS aggregators. I apologize for the inconvenience this must have caused you.

On a personal note, I am rather depressed right now. I installed MySQL and PHP on my XP Prof SP 1 laptop running IIS 5.1 and guess what, my IIS is now totally screwed up :-( I tried reinstalling IIS, PHP and even totally uninstalling PHP, but the problem still persists. In case you are interested, the problem is that I cannot bring up the web site properties for either the default web site or for any sub-webs. This essentially means I cannot administer IIS anymore and a complete OS reinstallation seems unavoidable now :-(

Read Full Post »

Sometimes you encounter a situation where you might have a relative file-path and you need to ensure that it’s not the same as another path you have (possibly another relative path). For example, “c:\text files\abc.txt” might be the same physical file as “..\..\abc.txt”. Luckily you don’t have to roll out your own custom function to verify whether they are both referring to the same physical file. Instead you can use the GetFullPathName (Kernel32.dll) Win32 API function to convert the relative path to the proper physical path of the filename. By the way one important thing to keep in mind is that GetFullPathName does not verify whether the calculated path is valid or whether it even exists.

The ArePathsSame function

bool ArePathsSame(LPCTSTR lpPath1, LPCTSTR lpPath2)
{
    bool ret = false;
    TCHAR lpBuffer1[MAX_PATH];
    LPTSTR lpFname1 = NULL;
    TCHAR lpBuffer2[MAX_PATH];
    LPTSTR lpFname2 = NULL;

    if( (GetFullPathName(lpPath1,MAX_PATH,
        lpBuffer1,&lpFname1) !=0)
        && (GetFullPathName(lpPath2,MAX_PATH,
        lpBuffer2,&lpFname2) != 0))
    {
        if(_tcsicmp(lpBuffer1,lpBuffer2) == 0)
            ret = true;
    }

    return ret;
}

Using the ArePathsSame function

SetCurrentDirectory("C:\\nish\\aoe2\\Screenshots");

bool bSame = ArePathsSame(
    "C:\\nish\\aoe2\\History\\Armies.txt",
    "..\\HISTORY\\Armies.txt");
if(bSame)
    cout << "Paths are physically the same\r\n";

Read Full Post »

Sometimes I do remember nostalgically, how in my early high-school days, I was quite thrilled on discovering the INKEY$ function in GWBASIC, which allowed me to implement a “Press any key to continue…” feature for my program. It somehow made my little GWBASIC programs seem more professional and cool.

10 PRINT "hello"
20 WHILE INKEY$=""
30 WEND
40 PRINT "bye"
50 END

Of course later on when I moved over to C/C++, the “Press any key…” functionality ceased to excite me any more because getch and getche were pretty commonly used CRT functions and it was no biggie to use them in my programs. I had very nearly forgotten about my adventures with “Press any key…” until the advent of .NET when I was stunned to realize that there was no managed way for me to incorporate a “Press any key…” feature for my console applications. I could use Console::Read or Console::ReadLine, but these functions waited till I pressed the [Return] key which was wholly unacceptable for my purposes.

Guess what? The Whidbey BCL has a Console::ReadKey(...) method! Woohoo! :-D

You can simply use Console::ReadKey() or you can use the overload that takes a bool parameter; you specify true to hide the pressed key and false to display the pressed key. The parameter-less ReadKey will display the pressed key, and internally it simply calls the other overload passing false as argument.

The ReadKey method returns a ConsoleKeyInfo object that can be used to examine the key/key-combination that was pressed. For example you can do fancy console stuff like this :-

Console::WriteLine(
    "Press Alt-F12 to exit, else keep looping like mad...");
while(true)
{
    ConsoleKeyInfo cki = Console::ReadKey(true);
    if(cki.Key == ConsoleKey::F12 &&
          cki.Modifiers == ConsoleModifiers::Alt)
        break;
}

A Ctrl-Break or a Ctrl-C will still break into the program though. For those interested, internally ReadKey calls the ReadConsoleInput and related Win32 API functions.

So now I can happily implement my “Press any key to continue…” feature and beam with pride at my really professional looking program ;-)

Read Full Post »

C++ programmers who want to write code targeting the CLR are now facing a rather complicated situation – the problem being that there is currently no C++ option that they can safely choose to write .NET code. Of course, there might be a few who would argue that we could use VC++.NET 2003 and use the managed extensions (MC++) – but, and it’s a very big “but” here, the problem is that the MC++ syntax is now obsolete. It will be supported in VC++.NET Whidbey through the /clr:oldSyntax compiler switch, but there is not much probability that it will be supported in future versions like Orcas (hope I spelled it right).

Not only that, when you start coding for Whidbey using C++/CLI, you’d then have to convert all your MC++ syntax code into the new syntax – even though you could get away with leaving some standalone code in the old syntax itself – but again that won’t be a very good idea nor a clean one. Another issue is that because of the differences in grammar between the old syntax and the new syntax, there is no one-to-one conversion option possible. So even if you come up with a few smart regexps and start converting your MC++ code into the new syntax, you’d still have to spend ages going through every single line of code to make sure things are okay.

Of course, now that the March 2004 Public Preview is out, you might be thinking that you could start writing .NET code using C++/CLI, but again you will be faced with a major problem. The C++/CLI compiler is still in a very early stage of infancy and most of the features have either not been implemented yet or been implemented in a slightly buggy manner – which is natural considering that it’s still in an Alpha stage as of now.

Now obviously Microsoft is not really at fault here – they brought out the MC++ syntax for us and got a lot of negative feedback from the developer community on the syntax/grammar. So they are now bringing out a much improved version which has even been standardized by the ECMA, but obviously they’d need time to get it up to shape. So essentially, while they are doing a very nice and civil thing for their trusted developer community, the major shift in syntax/grammar means that C++ programmers are left without a practical option for about an year and a little more.

The options for C++ developers are :-

  1. You could continue writing MC++ code until the C++/CLI compiler matures enough for it to be put to serious use
  2. You could start using the C++/CLI compiler once the first Beta is out
  3. You could stay away from .NET based coding with C++ until Whidbey is out

Of the three options (1) is not very smart and is actually pretty stupid if you consider everything. (2) is a bit risky, but C++ guys usually like to live on the edge and I’d strongly recommend that you go for it – you’d only have to wait another 3 months or so for the beta hopefully. (3) is obviously the safest option if you are okay with using C# for any unavoidable .NET programming requirements you might encounter.

Okay, that’s all I have to say for the moment. Now I’ll have to get Jambo and we’ll have to try and fix all those RSS feed errors that people have been reporting to us. There goes the weekend! *sigh*

Read Full Post »

IJW still works!

It would have been highly unlikely and extremely dumb if IJW did not work in C++/CLI, considering that the single most momentous feature in the Managed C++ language extensions was IJW. But I still wanted to try it out and did the usual <windows.h> inclusion and a call to the MessageBoxW API.

using namespace System;
using namespace stdcli::language;

#include <vcclr.h>
#include <windows.h>

ref class Hello
{
public:
    void Show(String^ text, String^ title)
    {
        pin_ptr<const Char> txt = PtrToStringChars(text);
        pin_ptr<const Char> titl = PtrToStringChars(title);
        MessageBoxW(GetDesktopWindow(), txt, titl, MB_OK);
    }
};

void _tmain()
{
    Hello^ h = gcnew Hello();
    h->Show("Hello Nish","IJW still works");
}

Oh boy, despite fully expecting it to work, I still felt most thrilled when I saw the message box pop up on my screen. For those who are not aware of managed-unmanaged string conversions, PtrToStringChars takes a String^ and returns an interior pointer to the CLR-heap location where the String object currently resides. But we cannot pass this pointer directly to the MessageBoxW function as the GC might come into play and invalidate the address pointed to by the interior pointer. So we need to pin the pointer in memory for the duration of the unmanaged function call.

C++/CLI introduces the pin_ptr keyword (or rather operator) which is defined in the stdcli::language namespace (which explains why I had to refer it on top of the program). All we need to do is to declare pinned local variables which we pass to the MessageBoxW function and voila – IJW does the rest!

Read Full Post »

Declaring classes in C++/CLI

Declaring classes in C++/CLI follows a much more coherent syntax than we had in Managed C++. On a side-note, the old syntax is nowadays referred to as Managed C++ and the new syntax is referred to as C++/CLI; some people do say old-managed syntax and new-managed syntax, but I think that’s just darn confusing, and prefer the former way of referring to the two syntaxes. In C++/CLI, CLR types are prefixed with an adjective that describes the type, and the adjective is left blank for native classes and structs. Examples are :-

  • class Native {...};
  • struct Native {...};
  • ref class ARefClass {...};
  • ref struct BRefClass {...};
  • value class CValClass {...};
  • interface class ISomeInterface {...};

Let’s see some example code :-

value class Student
{
public:
    String^ strStudentname;
};

interface class IHello
{
    void SayHello(Student student);
};

ref class Hello : public IHello
{
public:
    Hello()
    {
        Console::WriteLine("Hello from C++/CLI");
    }
    void SayHello(Student student)
    {
        Console::WriteLine("Hello {0}",
            student.strStudentname);
    }
};

Okay, so we have a value class Student, we have an interface IHello that defines a method that takes a Student argument, and then a class Hello that implements the IHello interface. Now let’s see some code to put these classes to use :-

void _tmain()
{
    Hello^ h = gcnew Hello();
    Student s;
    s.strStudentname = "Nish";
    h->SayHello(s);
}

Hmmm, those of you who haven’t seen the new syntax will be feeling a bit puzzled by the ^ symbol and the gcnew keyword. The ^ (called the cap symbol) punctuator represents a handle just as a * represents a pointer. According to the CLI specification a handle is a managed object reference. Handles are the new-syntax equivalent of __gc pointers in the MC++ syntax. Handles are not to be confused with pointers and are totally different in nature from pointers. Handles don’t really point to any specific memory location and are essentially tracking references to a managed object on the CLR heap that might keep changing physical locations based on GC cycles or heap compactions.

Just as new is used to instantiate native C++ objects, gcnew is used to instantiate CLR objects. gcnew returns a handle to a managed type that would have been allocated on the garbage collected CLR heap. The good thing about gcnew is that it allows us to easily differentiate between managed and unmanaged instantiations.

Anyway there’s nothing peculiar about our little program, and on compiling and running we get the expected output :-

Hello from C++/CLI
Hello Nish

You will need to compile with the /clr switch (which now defaults to /clr:newSyntax) and you won’t have to add a reference to mscorlib.dll as it is implicitly referenced.

Read Full Post »

New UI theme for blog

I’d like to profusely thank Paul Watson and Jambo Johnson for their incredibly awesome tips and suggestions while I was setting up the new UI-design for the blog. I’ve got to say this of those two guys; Paul Watson is a CSS genius par compare and Jambo is – well smart at everything he does.

I changed the theme as the code snippets didn’t look too good in the previous theme I was using, and I had to wrap my code-lines to awfully small lengths. Now I hope the blog is a lot more readable than it previously was :-)

Read Full Post »

The Microsoft Visual C++ Toolkit 2003 is now available as a free download – which means, all those of you out there who have not been able to upgrade to the latest version of VS.NET or VC++.NET due to monetary reasons, can still get to play with the latest C++ compiler/linker from Microsoft (including support for the CLR via the managed extensions). You have the entire CRT/STL and .NET BCL to fool around with though you won’t have MFC and ATL, but I doubt that you’ll miss MFC/ATL when you have the 1000s of BCL classes to use as an alternative.

It doesn’t come with a debugger though, and while you can use the .NET SDK debugger for managed code, you might want to get the Microsoft Debugging Tools (which is another free download) for debugging native code.

Read Full Post »

This is a technique I’ve used in the past to check for internet connectivity and it has never really failed to work for me. But I won’t say it’s a 100% safe method and you’ll have to verify that this works for your target environment before putting it into use.

BOOL CheckInternetConnection(LPCTSTR szURL)
{
    DWORD flags = 0;
    if( InternetGetConnectedState( &flags, 0 ) )
    {
        if( InternetCheckConnection( szURL,
            FLAG_ICC_FORCE_CONNECTION, 0 ) )
            return TRUE;
        else
            return FALSE;
    }
    else
        return FALSE;
}

And you can put the function to use as follows :-

if( CheckInternetConnection( "http://www.google.com" )
   || CheckInternetConnection( "http://www.microsoft.com" )
   || CheckInternetConnection( "http://www.yahoo.com" ) )
{
    // We are online
}
else
{
    // We are offline
}

You can replace the three web-sites I’ve used with your custom URLs if you want to do so, I just chose those three as I think the chances that all 3 of them are down at the same time are quite low.

Read Full Post »

Older Posts »

Follow

Get every new post delivered to your Inbox.