Code Sample: Wrapping Some Microsoft® Windows® API Functions

Wrapping File Open and Close

C++ allows defining an object to represent a resource such as an open file, a block of memory or a lock. Anything that must be closed, released, deallocated or freed can be defined in a class in which the destructor performs the terminal action. If we were to define a file class with a destructor that closes the file, the compiler will assure that the file is closed when the object is destroyed.

So one improvement that we can make toward more robust code is to wrap CreateFile and CloseHandle in a class. If we declare and instantiate a member variable of that type in our original function the file will automatically be closed when we return from the function. The compiler has now been instructed how to close the file and the responsibility for doing so has been passed from the programmer to the compiler.

Listing 1. The new File class.

class File {
    HANDLE hFile;
public:
    File(
        const char *name,
        DWORD access,
        DWORD shareMode,
        LPSECURITY_ATTRIBUTES pSecurityAttributes,
        DWORD creationDisposition,
        DWORD flagsAndAttributes,
        HANDLE templateFile
        ):
            hFile(INVALID_HANDLE_VALUE)
        {
            hFile=
                CreateFile(
                    name,
                    access,
                    shareMode,
                    pSecurityAttributes,
                    creationDisposition,
                    flagsAndAttributes,
                    templateFile
                );
	}
	~File()
	{
	    if ( hFile != INVALID_HANDLE_VALUE ) {
	        CloseHandle(hFile);
	    }
	}
	HANDLE getHandle() const
	{
	    return hFile;
	}
};

 

Listing 2. The base function, modified to use the File class.

void sample()
{
//  HANDLE hFile= CreateFile("sample.txt",GENERIC_READ,
//       0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
//  );
    File file("sample.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

//  if (hFile) {
    if (file.getHandle()) {
        // ... read the file content and display it
        const int bufsize= 200;
        char buffer[bufsize];
        DWORD bytesRead= 0;
//      if (ReadFile(hFile,buffer,bufsize,&bytesRead,NULL)) {
        if (ReadFile(file.getHandle(),buffer,bufsize,&bytesRead,NULL)) {
            buffer[bytesRead]= '\0';
            printf("%s\n",buffer);
        }
        else {
            printf("File read failed due to error #%ld\n",GetLastError());
        }
//      CloseHandle(hFile);
    }
}

The programmer no longer has to be aware of or concerned about how to open or close a file or whether the file must be explicitly closed. The line (File file(…);) not only declares and initializes the file object, it instructs the compiler to insert a destructor at the end of the enclosing block. In this case, when the function returns the destructor will be called and the file closed automatically.

Note that we had to define a getHandle function so that we can test whether the file was opened and so that we can pass a handle to the ReadFile function. This is evidence that we are not yet done defining our file class. Not only do we need to open and close the file, we need to verify that the file was opened and read data from the file. If we were to move that behavior into the File class we could eliminate the need to access the file handle outside the File class and eliminate the getHandle function.

As noted before, there are a number of API functions associated with a file handle. We will not wrap all file handle functions. We simply want to develop a reusable class to support our immediate needs. We need to read the file. To do so we will wrap the ReadFile function. Should we later need to write to a file or perform other operations on a file we can add that functionality to the File class.

[Previous: The base code] [Next: Fully Encapsulate the File Handle]


Microsoft and Windows are either registered trademarks or trademarks of Microsoft Corporation in the United States and/or other countries.

The Code Untangler home page

Copyright © 2001, Randy McLaughlin