UEFI开发探索46 – UEFI支持C++

请保留-> 【原文:  https://blog.csdn.net/luobing4365http://yiiyee.cn/blog/author/luobing/】

由于GUILite是由C++开发的,将其移植到UEFI下,意味着代码必须用C++来编写。

以下的内容,大部分来自于《UEFI原理与编程》第10章,将需要的代码整合到了我自己的框架中。有些书中没有遇到的小问题,博客中也给了解决办法。

1 C与C++之于UEFI

UEFI中的程序遵循的是C语言的规则,大部分时候应该用模块化的思维方式去理解代码。在日常开发的时候并没有什么问题,何况C语言比C++更适合直接与硬件打交道的场景。不过,遇到稍大点的GUI应用,或者移植遗留的C++代码时,就不得不采用C++了。比如这次的GuiLite的移植工作。

在windows下,开发所用的工具是Visual Studio,编译器cl本身就是支持C++的。因此,我们所要做的工作是让UEFI的入口函数能够“认识”C++的代码。

C++与C的主要区别在于函数名、数组名等,在经过编译后会不同。这是名字修饰的过程,大部分编译原理的书籍中都有描述过。因此,如果直接用C的代码去调用C++的库,会导致链接失败的。

为了支持C++,EDK2在后续的版本中,也逐渐地添加了一些支持。比如在生成的中间文件AutoGen.h中,自动添加了extern “C”,解决了中间文件的名字修饰问题。

我的开发环境是UDK2018+VS2015,在Win10上进行开发的。

2 支持基础的类

基本上进行以下四个步骤,就可以支持C++的类的功能了。

1) 解决名字修饰问题

这个问题比较简单,只需要在C++源文件中,将C语言的头文件用extern “C”包含起来就可以了。如图:

图1 c与C++的名字修饰问题

对于老版本EDK2中的AutoGen.h未解决名字修饰问题,在我现在用的这个版本已经接近了,可以忽略掉。

2) 在C++中使用NULL

想要在UEFI的C++代码中使用NULL,需要重新定义:

#undef  NULL
#define  NULL 0

3) 在C++中使用布尔型

可以在inf文件中修改编译选项来解决:

图2 解决布尔型变量使用的问题

4) /Zc:wchar_t问题

我的示例代码,会使用StdLib中的函数。编译的时候提示这个错误:

图3 宽字符类型的报错

直接在EfiCdefs.h中,将330行的语句注释掉就行了。

图4 EfiCdefs.h的改写

经过上述四个步骤,UEFI的代码就可以支持基础的类了。包括类的构造函数和析构函数、派生等,都可以支持。不过,如果需要支持类的全局实例化,还需要做些工作。

3 类的全局实例化

这里我直接借用了《UEFI原理与编程》中的代码。

具体来说,可以从汇编语言观察C++的如何进行全局构建与全局析构的。模仿其流程,在执行实际应用代码的前后,处理全局的类实例。

这种方法比较复杂,具体的可以参考原书的说明。需要注意的是,这是windows平台Visual studio的处理方法,换一个平台或者编译器,代码都不能通用。

这是搭建好的代码框架:

图5 UEFI的C++框架代码

其中,crt0data.cpp来自于上述参考书中的代码,为了表明出处,源文件的名字我也保留了。

至此,框架搭建完毕。至于支持new和delete的内存处理方式,在GUILite中并没有用到,我就不添加了。

百度云链接:https://pan.baidu.com/s/1gccSosw8_UAGTI5gZPnLCA
提取码:dx23
文件在 FF RobinPkg/ RobinPkg /Applications/CppMain

548 total views, 4 views today

《UEFI开发探索46 – UEFI支持C++》有2个想法

发表评论

电子邮件地址不会被公开。