LIB (Static Library – 静态库)和 DLL (Dynamic Link Library – 动态链接库) 都是库文件,他们存在一些差别。比如,LIB 是编译期加入到文件中,成为 EFI 或者 EXE 的一部分。而DLL则是在运行期独立存放在内存中进行调用的。
这次的实验是:在 VS2019 中使用C生成一个 LIB, 然后在 EDK2 环境下调用这个LIB。
首先编写 LIB ,源代码非常简单,LibFile.c 源代码如下:
///
/// 8-byte unsigned value
///
typedef unsigned long long int UINT64;
///
/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions,
/// 8 bytes on supported 64-bit processor instructions)
///
typedef UINT64 UINTN;
#define EFIAPI __cdecl // Force C calling convention for Microsoft C compiler
#define IN
UINTN
EFIAPI
MyLibAdd(
IN UINTN A,
IN UINTN B
)
{
return A + B;
}
项目属性中设置编译目标为 Lib:

Debug 信息格式设置为 /Z7:

Runtime Library 设置为 /MTd

编译之后就得到了 LibFile.lib 文件。
接下来在 EDK2 中编写代码。
代码非常简单,关键点在于 extern 告诉链接器将要从外部调用 MyLibAdd() 函数。
#include <Uefi.h>
#include <Library/UefiLib.h>
#include <Library/ShellCEntryLib.h>
extern UINTN EFIAPI MyLibAdd(IN UINTN A,IN UINTN B);
INTN
EFIAPI
ShellAppMain (
IN UINTN Argc,
IN CHAR16 **Argv
)
{
Print(L"LibTest Result: %d \n",MyLibAdd(1,2));
return(0);
}
接下来编写 INF 文件,关键点在于 MSFT:*_*_*_DLINK_FLAGS 告诉 Lib 所在的目录位置。
[Defines]
INF_VERSION = 0x00010006
BASE_NAME = libtest
FILE_GUID = a912f198-7f0e-2026-0429-b757b806ec83
MODULE_TYPE = UEFI_APPLICATION
VERSION_STRING = 0.1
ENTRY_POINT = ShellCEntryLib
#
# VALID_ARCHITECTURES = IA32 X64
#
[Sources]
LibTest.c
[Binaries]
LIB|LibFile.lib
[Packages]
MdePkg/MdePkg.dec
ShellPkg/ShellPkg.dec
[LibraryClasses]
UefiLib
ShellCEntryLib
[BuildOptions]
MSFT:*_*_*_DLINK_FLAGS = /LIBPATH:$(WORKSPACE)/AppPkg/Applications/LibTest LibFile.lib
特别注意:生成的 Lib 可以有 IA32 也可以有 X64, 同时还有 Release 和Debug 版本的区别,不可以混用。相对的,如果你要提供 LIB 给他人使用,那么很可能需要同时提供 Release 和 Debug 两个版本。本次实验测试的是 X64 Lib, Debug 版本。对应的编译命令是(Default 是 Debug 版本):
build -a X64 -p AppPkg\AppPkg.dsc -t VS2019
编译后的文件在模拟器中测试:

本次实验的VC 工程文件在这里下载:
本次实验的 EDK2 代码在这里下载: