前面介绍过 UEFI 下获得命令行参数的方法。这次尝试用 C Lib 来实现。
需要获取的参数直接用下面的代码进行输出
for (i=0;i<Argc; i++)
{
printf("Arg[%d]: %s\n",i,Argv[i]);
}
惊奇的发现,只能输出每个参数的第一个字母,一下子蒙了。琢磨了好长时间,忽然想起来这个应该是 unicode导致的。正常情况下
“abc”这样的ascii在unicode中会被存为 “97 00 98 0 99 0”,遇到 00 printf 自动就给截断了
顺手查了一下 \StdLib\Include\stdio.h ,其中提到了这个事情
If an l length modifier is present, the argument shall be a
pointer to the initial element of an array of wchar_t type. Wide
characters from the array are converted to multibyte characters
(each as if by a call to the wcrtomb function, with the conversion
state described by an mbstate_t object initialized to zero before
the first wide character is converted) up to and including a
terminating null wide character. The resulting multibyte characters
are written up to (but not including) the terminating null
character (byte). If no precision is specified, the array shall
contain a null wide character. If a precision is specified, no more
than that many bytes are written (including shift sequences, if
any), and the array shall contain a null wide character if, to
equal the multibyte character sequence length given by the
precision, the function would need to access a wide character one
past the end of the array. In no case is a partial multibyte
character written.
那我再试试
for (i=0;i<Argc; i++)
{
printf("Arg[%d]: %ls\n",i,Argv[i]);
}
结果依旧。不知道为什么了,如果有了解的朋友可以给我写邮件告诉我。
好在我们还有 Print 和 wprintf 可以绕过去。最后写了一个程序,主要代码如下
#include <Uefi.h> #include <Library/UefiLib.h> #include <Library/ShellCEntryLib.h> #include <stdio.h> #include <wchar.h> /*** Demonstrates basic workings of the main() function by displaying a welcoming message. Note that the UEFI command line is composed of 16-bit UCS2 wide characters. The easiest way to access the command line parameters is to cast Argv as: wchar_t **wArgv = (wchar_t **)Argv; @param[in] Argc Number of argument tokens pointed to by Argv. @param[in] Argv Array of Argc pointers to command line tokens. @retval 0 The application exited normally. @retval Other An error occurred. ***/ int EFIAPI main ( IN int Argc, IN char **Argv ) { int i; printf("You have input %d args\n",Argc); printf("\nExp1. If we use \" printf(\"Arg[%%d]: %%s\\n\",i,Argv[i]);\n"); for (i=0;i<Argc; i++) { printf("Arg[%d]: %s\n",i,Argv[i]); } printf("\nExp2. If we use \" printf(\"Arg[%%d]: %%ls\\n\",i,Argv[i]);\n"); for (i=0;i<Argc; i++) { printf("Arg[%d]: %ls\n",i,Argv[i]); } printf("\nExp3. If we use \" Print(L\"Arg[%%d]: %%s\\n\",i,Argv[i]);\n"); for (i=0;i<Argc; i++) { Print(L"Arg[%d]: %s\n",i,Argv[i]); } printf("\nExp4. If we use \" wprintf(L\"Arg[%%d]: %%s\\n\",i,Argv[i]);\n"); for (i=0;i<Argc; i++) { wprintf(L"Arg[%d]: %ls\n",i,Argv[i]); } return EFI_SUCCESS; }
最终的运行结果
代码下载:Main (和前面几篇文章一样,请用 AppPkg 编译)
不知道为什么会有这样的结果 char的话就是单字节,不应该出现双字节的问题
我在实机(x64)测试了一下 只有
printf("Arg[%d]: %s\n",i,Argv[i]);
会正常显示
我测试了一下,sizeof(char) 确实是 1
现在不清楚为什么会出现这样的结果.....
按照你图片的结果,你应该是接收到了一个双字节字符串的指针。
也许是EDK版本问题,也可能是SHELL的问题。
总之你想要接收一个单字节的命令行地址,系统却传给你了一个双字节的。
不过EDK中默认用的是双字节,而且上面也说了 想要访问命令行要转换类型
Note that the UEFI command line is composed of 16-bit UCS2 wide characters.
The easiest way to access the command line parameters is to cast Argv as:
wchar_t **wArgv = (wchar_t **)Argv;
可我在实机测试的结果却是接收到的单字节,也许是我用的shell 自动转换了?
你有没有试一下 去掉 int EFIAPI main 的 EFIAPI
int main ( IN int Argc, IN char **Argv )
具体怎么做? 不懂