- 论坛徽章:
- 2
|
回复 #1 千江有月 的帖子
lz你这个需求我曾经也考虑过, 不过没能想出仅仅用C语言解决的办法…… 需要依赖于构建工具…… 比如windows上的资源文件与资源编译器。
xnix下可以用objcopy。 感觉比资源文件更方便直接。
下面是一个例子:
-------- -------- -------- -------- 1. 编写被嵌入的文件 -------- -------- -------- --------
hello.html
<p>
hello "world"
</p>
共26字节: 3 + 13 + 4 + 3个换行 —— 我在windows下, 所以行结束符是\r\n。
-------- -------- -------- -------- 2. 生成目标文件 -------- -------- -------- --------
objcopy -I binary -O pe-i386 -B i386 hello.html hello.o
生成的目标文件, hello.o 包含3个符号:
objdump -t hello.o
hello.o: file format pe-i386
SYMBOL TABLE:
[ 0](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000 _binary_hello_html_start
[ 1](sec 1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000001a _binary_hello_html_end
[ 2](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000001a _binary_hello_html_size
-------- -------- -------- -------- 3. 为这些符号生成正确的C语言声明。 -------- -------- -------- --------
借此地顺便鄙视一下坛里某位不知道如何在头文件里声明全局变量的同学。C简单又怎样, 以你那态度和水平, 拽个p
hello.h
extern const char binary_hello_html_start[];
extern const char binary_hello_html_end[];
为了示例代码简洁, 此处省略了头文件保护符,也不打算编写正确的extern "C"以提供给C++翻译单元使用了。
-------- -------- -------- -------- 4. 使用这些变量 -------- -------- -------- --------
编写一个简单的用户。
client.c
#include <stdio.h>
#include "hello.h"
int main(void)
{
const char* p = binary_hello_html_start;
ptrdiff_t length = binary_hello_html_end - binary_hello_html_start;
printf("length=%d content:\n\"",(int)length);
for (; p != binary_hello_html_end; ++p )
printf("%c", *p);
printf("\"\n" ); // 此处为了清晰, 在输出内容前后加上了双引号
return 0;
}
gcc -Wall -c client.o
gcc client.o hello.o
a
输出:
length=26 content:
"<p>
hello "world"
</p>
"
-------- -------- -------- -------- 一些说明: -------- -------- -------- --------
再次声明一下…… 我是在windows上编写与实验这些代码的……
所以xnix的构建工具很不熟悉……
所以objcopy 使用的是pe-i386…… 可能需要换作elf-i386
-------- -------- -------- -------- 1. 关于这3个符号: -------- -------- -------- --------
_binary_hello_html_start
_binary_hello_html_end
_binary_hello_html_size
-------- -------- 1.1 size -------- --------
前2者在链接的时候, 是会被重定位的。 而xxx_size 不会………………
不知道是我用错了, 还是说这就是objcopy的本意……
要使用 _binary_hello_html_size 也行…… 很麻烦……
extern T binary_hello_html_size; // 随便什么类型
ptrdiff_t length = (ptrdiff_t)&binary_hello_html_size; // 需要的是它的地址。
所以, 还是这样取得长度比较方便:
ptrdiff_t length = binary_hello_html_end - binary_hello_html_start;
-------- -------- 1.2 start, end -------- --------
binary_hello_html_start, binary_hello_html_end 应声明为数组型。
这里涉及指针和数组的重大区别 —— 指针会多一次访问。
这又让我想上面提到的那位浮躁的同学 …… 以及某跟风的机器阿Q…… 睁大眼睛看清楚了
_binary_hello_html_start : 这个符号标识着这段html内容的地址
'<' , 'p', '>' , '\r', '\n' ...
1. 如果binary_hello_html_start被声明为char 的数组, 那么编译器对如下C代码:
binary_hello_html_start[idx]
生成的伪代码如下:
1. p1 = _binary_hello_html_start ; 以 _binary_hello_html_start 为起始地址
2. p2 = p1 + idx ; 再加上偏移
3. c = byte[ p2 ] ; 并访问
合起来就是:
byte[ _binary_hello_html_start + idx ]
这样就能正确访问html的内容。
2. 如果binary_hello_html_start被声明为char 的指针, 那么编译器对如下C代码:
binary_hello_html_start[idx]
生成如下伪代码:
1. p1 = dword [_binary_hello_html_start] ; 从_binary_hello_html_start处取得一个指针值作为起始地址
2. p2 = p1 + idx ; 由上面的指针值再加上偏移
3. c = byte[p2] ; 并访问
合起来就是:
byte[ dword[_binary_hello_html_start] + idx ]
通过指针访问相比通过数组访问的不同就在于: 指针多出上面的第1步的访问。
对于这个例子来说, 就是不对的, 编译器生成的代码会把 '<' , 'p' , '>', '\r' 解释为一个地址, 然后访问这个地址。
所以对这个例子而言, 声明为数组是最方便的。
-------- -------- -------- -------- 2. 不依赖工具 -------- -------- -------- --------
有没有不依赖工具, 仅仅使用C语言就可以完成这个需求的方案啊……
高手们分享一下嘛 
[ 本帖最后由 OwnWaterloo 于 2009-12-27 02:25 编辑 ] |
|