UEFI News and Commentary

Sunday, May 21, 2017

Using C++ With EDK2, Part 1: new and delete

This is the first in a series of articles looking at what it takes to compile a UEFI C++ application under EDK2. This isn't an attempt to cover everything. I'm not a compiler library expert, so I'm not trying to port everything in the STL over. Nor am I a regular GCC user, so my efforts have been focused on Visual Studio 2015. Finally, I am focused on UEFI Shell applications, rather than normal UEFI apps or UEFI drivers.

I was initially intrigued by the fact that "#ifdef __cplusplus" occurs in several places. It appears in the StdLib header files, but that makes sense since they were originally a port from an environment that supported C++ and C. It also appears in the AutoGen.h files that are automatically created by the EDK2 build system for each module. It looks something like this:

#ifdef __cplusplus
extern "C" {
#endif

#include
#include
#include

extern GUID  gEfiCallerIdGuid;
extern CHAR8 *gEfiCallerBaseName;
...

// Guids
extern EFI_GUID gEfiAuthenticatedVariableGuid;
extern EFI_GUID gEfiVariableGuid;
...

// Definition of PCDs used in this module
#define _PCD_TOKEN_PcdFlashNvStorageVariableBase  5U
...
EFI_STATUS
EFIAPI
PeimInitializeVariableServices (
  IN       EFI_PEI_FILE_HANDLE  FileHandle,
  IN CONST EFI_PEI_SERVICES     **PeiServices
  );
...
#ifdef __cplusplus
}
#endif

That is, all of the C symbols that are automatically included into the build have the extern "C" linkage specifier placed around them so that they will handle calls from either C or C++ source code. So someone was thinking about C++.

For my solution, which is checked in on SourceForge here, I started simply by handling the necessary support for the new and delete operators, with no support for exceptions. This C++ library depends on the StdLib C library that comes with EDK2. For the most part, the C headers would work just fine, but two critical files (MdePkg/Include/Base.h and StdLib/Include/sys/EfiCDefs.h) generate errors when pulled in to C++ code. For now, I simply created new, slightly modified versions to work around the minor issues. This requres that your .inf file list the new library before listing the StdLib.

[Packages]
  SysLib/SysLib.dec
  StdLib/Stdlib.dec

This changes the include order so that, if there is a modified version for the C++ library, it will be preferred over the one in StdLib.

So far, only the new header file declares anything of substance. The others (wchar.h, stdlib.h, stdio.h) just provide wrappers for the StdLib that bring in the versions of Base.h and EfiCDefs.h that work with the library.

But the results are pretty nice. Assuming you don't need exception handling or the C++ standard library, you can use all of the normal C++ features, such as classes and inheritance and templates.

This is just the starting point. Over the next articles, I will expand the support for both the C++ and C libraries.