根据我学到的“最佳实践”,我们应该将程序需要的资源加载到RAM中,避免对用户硬盘的不必要请求。使用SDL2时,我总是在将图像文件加载到RAM后释放它们。(文件->表面->纹理->释放文件/表面)。因此,如果其他应用程序更改了文件,则我的程序会忽略它,因为文件不再被它使用。
现在,在第16课中,我正在学习如何使用附加组件SDL_ttf
。
然而,使用SDL_ttf
附加组件时,我找不到一种方法来释放font.ttf
文件,也将其加载到RAM中。我只能通过指针看到它。在我渲染文本时,似乎文件仍然被读取。
如何将它加载到RAM中,以便呈现调用RAM位置,而不是HD中的文件?
完整代码
#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>
int G = 255;
int main (void) {SDL_SetMainReady();
int SCREEN_WIDTH = 800;
int SCREEN_HEIGHT = 600;
bool QUIT_APPLICATION = false;
SDL_Event union_Event_manager;
SDL_Color str_White_colour = {255,255,255,255};
SDL_Window * ptr_Window = nullptr;
SDL_Surface * ptr_Text_Surface = nullptr;
SDL_Surface * ptr_Main_surface = nullptr;
SDL_RWops * ptr_str_rwops = nullptr;
TTF_Font * ptr_Font = nullptr;
SDL_Init(SDL_INIT_VIDEO);
TTF_Init();
ptr_Window = SDL_CreateWindow("Lesson 16 - TrueTypeFonts", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN);
ptr_Main_surface = SDL_GetWindowSurface(ptr_Window);
ptr_str_rwops = SDL_RWFromFile("FreeMono.ttf", "r");
ptr_Font = TTF_OpenFontIndexRW(ptr_str_rwops, 1, 72, 0);
ptr_Text_Surface = TTF_RenderText_Solid(ptr_Font, "Hello World", str_White_colour);
while(!QUIT_APPLICATION){
while(SDL_PollEvent(&union_Event_manager) != 0 ){
if (union_Event_manager.type == SDL_QUIT) {QUIT_APPLICATION = true;}
/*END WHILE*/}
SDL_BlitSurface(ptr_Text_Surface, NULL, ptr_Main_surface, NULL);
SDL_UpdateWindowSurface(ptr_Window);
/*END WHILE*/}
TTF_CloseFont(ptr_Font);
// if called before any rendering, the app crashes, as supposed to.
// So, how free the **file** and keep using its content from RAM?
SDL_RWclose(ptr_str_rwops);
SDL_FreeSurface(ptr_Text_Surface);
SDL_FreeSurface(ptr_Main_surface);
SDL_DestroyWindow(ptr_Window);
ptr_Font = nullptr;
ptr_str_rwops = nullptr;
ptr_Text_Surface = nullptr;
ptr_Main_surface = nullptr;
ptr_Window = nullptr;
TTF_Quit();
SDL_Quit();
return (0);}
失败1:
创建一个结构来保存文件中的信息。
TTF_Font str_Font; // Error in compilation ''incomplete type''
str_Font = *ptr_Font;
TTF_CloseFont(ptr_Font);
ptr_Font = nullptr;
ptr_Font = &str_Font;
失败原因:
我误解了文件的工作方式。这个结构体只保存有关文件的信息,而不是媒体本身。这种方法是无用的,释放指针后程序会崩溃(呈现尝试解引用一个 nullptr
)。
失败2:
使用内置函数释放资源。
ptr_Font = TTF_OpenFontIndexRW(SDL_RWFromFile("FreeMono.ttf", "r"), 1, 72, 0);
失败原因: 我不明白为什么第二个参数(非零)指定在使用后应该释放资源。这也发生在上面完成的源代码中,我只是将函数分成两行。
失败3:
创建结构以保存有关指针的信息。
ptr_str_rwops = SDL_RWFromFile("FreeMono.ttf", "r");
str_rwops = *ptr_str_rwops;
SDL_RWclose(ptr_str_rwops); // crashes the program
ptr_str_rwops = nullptr;
ptr_str_rwops = &str_rwops; // useless: file still in use.
故障原因: 结构RWops似乎不能持有文件,只能存储文件相关信息。因此,它是故障1和2的总和。
故障4:
尝试将文件作为对象加载。
ptr_LoadObject = (TTF_Font*)SDL_LoadObject("FreeMono.ttf");
ptr_str_rwops = SDL_RWFromFile((const char *)ptr_LoadObject, "r");
故障原因: 该功能与共享操作系统文件一起使用。函数使用错误。
更新于2019-04-05
故障5
尝试使用memcpy直接将文件复制到RAM中。
long int func_discover_file_size(char* file){
long int var_file_size = 0;
FILE * ptr_file = nullptr;
ptr_file = fopen(file, "rb");
fseek(ptr_file , 0L , SEEK_END);
var_file_size = ftell(ptr_file);
fclose(ptr_file);
return var_file_size;
/*END func_discover_file_size*/}
int main (void) {
/*cut unrelated code*/
void * ptr_load_file = nullptr;
void * ptr_File_copy = nullptr;
long int var_file_size = 0;
/*cut unrelated code*/
var_file_size = func_discover_file_size("FreeMono.ttf");
// works fine and returns correct size of file.
ptr_File_copy = (char*) calloc (1, var_file_size);
// memory allocation works fine (tested)
ptr_load_file = fopen("FreeMono.ttf", "rb");
// file loaded correctly. Test with FOR LOOP shows content of file in console.
memcpy(ptr_File_copy, ptr_load_file, var_file_size);
// program crashes in line above
失败原因: 看起来我不知道如何正确使用memcpy。我尝试了许多函数和指针的转换(void,char),尝试将指针类型更改为char、void、FILE,尝试输出到第三个指针...
现在我正在寻找一个好心灵来启迪我的方法... :-p
注意:标记为C,因为SDL
fread
函数从FILE*
读取:fread(ptr_File_copy, 1, var_file_size, ptr_load_file)
,而不是使用memcpy。 - keltar