为什么 SDL2 渲染器不向我的 window 绘制任何内容?
Why doesn't the SDL2 Renderer draw anything to my window?
我目前正在使用 C 编写 Chip-8 解释器。对于渲染,我使用 SDL2 库。问题是我无法在屏幕上绘制矩形。 SDL_RenderClear 函数也不起作用。也许是 Makefile 但我已经尝试将链接器中的控制台标志更改为 windows。谁能帮帮我?
我的代码:
main.c
#include "chip.h"
#define NO_ROM_INSERTED 1
const int PIXEL_SIZE = 20;
const int CHIP_WIDTH = 64;
const int CHIP_HEIGHT = 32;
const int SCREEN_WIDTH = CHIP_WIDTH * PIXEL_SIZE;
const int SCREEN_HEIGHT = CHIP_HEIGHT * PIXEL_SIZE;
int main(int argc, char **argv)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Event event;
int quit = 0;
Chip *chip = (Chip*)malloc(sizeof(Chip));
chipInitialize(chip);
chip->gfx[23] = 0x01;
/*Checks if a ROM file is inserted by an argument*/
if(argc < 2)
{
printf("Error, no Rom inserted");
return NO_ROM_INSERTED;
}
else
{
printf("\n%s loaded into memory\n", argv[argc-1]);
}
loadProgramInMemory(chip, "./Roms/TETRIS");
if(!init(window, renderer, SCREEN_WIDTH, SCREEN_HEIGHT))
{
printf( "Failed to initialize!\n" );
}
else
{
while(!quit)
{
while(SDL_PollEvent(&event) != 0)
{
if(event.type == SDL_QUIT)
{
quit = 1;
}
}
// Clear screen
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
SDL_RenderClear(renderer);
for(int i = 0; i < CHIP_HEIGHT; i++)
{
for(int j = 0; j < CHIP_WIDTH; j++)
{
if(chip->gfx[i * CHIP_WIDTH + j] > 0x00) //Translates the one dimensional gfx to two dimensional screen
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_Rect fillRect = {CHIP_WIDTH * i, CHIP_HEIGHT * j, PIXEL_SIZE, PIXEL_SIZE};
SDL_RenderFillRect(renderer, &fillRect);
}
}
}
// Update screen
SDL_RenderPresent(renderer);
}
}
close(window, renderer);
free(chip);
return 0;
}
chip.h
#include "window.h"
typedef struct chip{
unsigned char memory[4096];
unsigned short opcode;
unsigned short pc;
unsigned short stack[16];
unsigned short sp;
unsigned char gfx[64 * 32];
unsigned char V[16];
unsigned short I;
unsigned char delayTimer;
unsigned char soundTimer;
}Chip;
void chipInitialize(Chip *chip);
void loadFontInMemory(Chip *chip);
void loadProgramInMemory(Chip *chip, char *program);
chip.c
#include "chip.h"
void chipInitialize(Chip *chip)
{
chip->pc = 0x200; // Set program counter to 0x200
chip->opcode = 0x0000; // Reset current opcode
chip->I = 0x0000; // Reset index register
chip->sp = 0x0000; // Reset stack pointer
chip->delayTimer = 0x00; // Reset delay timer
chip->soundTimer = 0x00; // Reset sound timer
for(int i = 0; i < 64 * 32; i++) // Reset the graphics
chip->gfx[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset the stack
chip->stack[i] = 0x0000;
for(int i = 0; i < 4069; i++) // Reset memory
chip->memory[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset registers
chip->V[i] = 0x00;
loadFontInMemory(chip); // Loads the font-set into memory
}
void loadProgramInMemory(Chip *chip, char *program)
{
int bufferSize = 0xFFF - 0x200; // Size of the memory which is reserved for the program
unsigned char buffer[bufferSize];
FILE *ptr;
ptr = fopen(program, "rb");
fread(buffer, bufferSize, 1, ptr);
for(int i = 0; i < bufferSize; i++)
chip->memory[i + 512] = buffer[i]; // Reads in the program and stores it in memory at location 0x200 or 512
}
void loadFontInMemory(Chip *chip)
{
// Zero // Six // C
chip->memory[0x000] = 0xF0; chip->memory[0x01E] = 0xF0; chip->memory[0x03C] = 0xF0;
chip->memory[0x001] = 0x90; chip->memory[0x01F] = 0x80; chip->memory[0x03D] = 0x80;
chip->memory[0x002] = 0x90; chip->memory[0x020] = 0xF0; chip->memory[0x03E] = 0x80;
chip->memory[0x003] = 0x90; chip->memory[0x021] = 0x90; chip->memory[0x03F] = 0x80;
chip->memory[0x004] = 0xF0; chip->memory[0x022] = 0xF0; chip->memory[0x040] = 0xF0;
// One // Seven // D
chip->memory[0x005] = 0x20; chip->memory[0x023] = 0xF0; chip->memory[0x041] = 0xE0;
chip->memory[0x006] = 0x60; chip->memory[0x024] = 0x10; chip->memory[0x042] = 0x90;
chip->memory[0x007] = 0x20; chip->memory[0x025] = 0x20; chip->memory[0x043] = 0x90;
chip->memory[0x008] = 0x20; chip->memory[0x026] = 0x40; chip->memory[0x044] = 0x90;
chip->memory[0x009] = 0x70; chip->memory[0x027] = 0x40; chip->memory[0x045] = 0xE0;
// Two // Eight // E
chip->memory[0x00A] = 0xF0; chip->memory[0x028] = 0xF0; chip->memory[0x046] = 0xF0;
chip->memory[0x00B] = 0x10; chip->memory[0x029] = 0x90; chip->memory[0x047] = 0x80;
chip->memory[0x00C] = 0xF0; chip->memory[0x02A] = 0xF0; chip->memory[0x048] = 0xF0;
chip->memory[0x00D] = 0x80; chip->memory[0x02B] = 0x90; chip->memory[0x049] = 0x80;
chip->memory[0x00E] = 0xF0; chip->memory[0x02C] = 0xF0; chip->memory[0x04A] = 0xF0;
// Three // Nine // F
chip->memory[0x00F] = 0xF0; chip->memory[0x02D] = 0xF0; chip->memory[0x04B] = 0xF0;
chip->memory[0x010] = 0x10; chip->memory[0x02E] = 0x90; chip->memory[0x04C] = 0x80;
chip->memory[0x011] = 0xF0; chip->memory[0x02F] = 0xF0; chip->memory[0x04D] = 0xF0;
chip->memory[0x012] = 0x10; chip->memory[0x030] = 0x10; chip->memory[0x04E] = 0x80;
chip->memory[0x013] = 0xF0; chip->memory[0x031] = 0xF0; chip->memory[0x04F] = 0x80;
// Four // A
chip->memory[0x014] = 0x90; chip->memory[0x032] = 0xF0;
chip->memory[0x015] = 0x90; chip->memory[0x033] = 0x90;
chip->memory[0x016] = 0xF0; chip->memory[0x034] = 0xF0;
chip->memory[0x017] = 0x10; chip->memory[0x035] = 0x90;
chip->memory[0x018] = 0x10; chip->memory[0x036] = 0x90;
// Five // B
chip->memory[0x019] = 0xF0; chip->memory[0x037] = 0xE0;
chip->memory[0x01A] = 0x80; chip->memory[0x038] = 0x90;
chip->memory[0x01B] = 0xF0; chip->memory[0x039] = 0xE0;
chip->memory[0x01C] = 0x10; chip->memory[0x03A] = 0x90;
chip->memory[0x01D] = 0xF0; chip->memory[0x03B] = 0xE0;
}
window.h
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
int init(SDL_Window *window, SDL_Renderer* renderer, const
int width, const int height);
void close(SDL_Window *window, SDL_Renderer* renderer);
window.c
#include "window.h"
int init(SDL_Window *window, SDL_Renderer *renderer, const
int width, const int height)
{
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
return success;
}
void close(SDL_Window *window, SDL_Renderer* renderer)
{
//Destroy window
SDL_DestroyWindow( window );
window = NULL;
SDL_DestroyRenderer(renderer);
renderer = NULL;
//Quit SDL subsystems
SDL_Quit();
}
生成文件
OBJS = main.c chip.c window.c
OBJ_NAME = Emulator
all : $(OBJS)
gcc $(OBJS) -IC:\code\SDL2\i686-w64-mingw32\include -LC:\code\SDL2\i686-w64-mingw32\lib -w -Wl,-subsystem,console -lmingw32 -lSDL2main -lSDL2 -o $(OBJ_NAME)
让我从一个建议开始 - 如果您对答案完全感兴趣,请不要让回答您的问题变得比需要的更难。想想它在其他人看来的样子——一些大量的代码,似乎没有绘制任何东西的问题;为什么这个例子必须有 6 个文件?为什么它依赖于我们没有的外部文件,因此实际上无法验证?当然,仅使用 init 和 render 就可以将其缩减为 30 行单个文件 - 实际上,SDL2 的任何 "hello world" 都可以。当它有效而您的代码无效时 - 您开始检查有什么不同。
现在回答你的问题。你不能从你的主循环中提取任何东西,因为你的 window
和 renderer
这里是 NULL - 它被初始化为 NULL 并且从未设置为任何其他东西。看来您对函数参数的工作方式有误解 - 在 C 中,函数参数是按值传递的,并且对该值的任何修改都是对本地函数副本进行的。当您传递一个 int 时,函数会获取该 int 的副本,并且不会推回任何更改。如果传递 SDL_Window*
,则传递该指针的 value(在您的情况下,NULL
);当您执行 SDL_CreateWindow
时,您将其分配给局部变量,并且再次无法 return 将其返回给调用者,它保持为 NULL。因此,您所有的渲染调用都将 NULL 作为渲染器传递,这自然不是有效的渲染器。
同样的事情出现在你的 close
- 你试图将传递的副本重置为 NULL,但这没有任何意义,因为你不能修改外部值,只能修改函数本地副本。
编程 类 经常教导有 "pass by value" 和 "pass by reference",我想这是混淆的根源。我宁愿说 C 中没有按引用传递,你总是传递值,但指针也是一个值。为了能够修改数据,我们将指针传递给该数据;要改变 int,您可以传递 int*
,但要改变 SDL_Window*
,您需要获得指向 that 指针的指针 - SDL_Window**
。看看 SDL 本身是如何做到的:https://wiki.libsdl.org/SDL_CreateWindowAndRenderer .
所以,简而言之 - 让你的 init
变成 int init(SDL_Window **window, SDL_Renderer** renderer, int width, int height);
(你在这里也不需要 const int
,因为这些是宽度和高度的副本),并且相应地修改其代码。并在调用后检查 window
和 renderer
的值(调试器、调试 printf、if(window==NULL)
一切正常)。 init
可能类似于
int init(SDL_Window **owindow, SDL_Renderer **orenderer,
int width, int height)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
*owindow = window;
*orenderer = renderer;
return success;
}
当然调用init
必须修改为init(&window, &renderer, SCREEN_WIDTH, SCREEN_HEIGHT)
。
虽然我们正在做这件事,但还有两件事:
头文件应该有 include guards 否则如果你多次(直接或间接)包含它会导致问题。
永远不要调用你的函数 close
。它会(没有任何问题)在 linux/UNIX 系统上崩溃。考虑另一个未被广泛操作系统保留的名称。
我目前正在使用 C 编写 Chip-8 解释器。对于渲染,我使用 SDL2 库。问题是我无法在屏幕上绘制矩形。 SDL_RenderClear 函数也不起作用。也许是 Makefile 但我已经尝试将链接器中的控制台标志更改为 windows。谁能帮帮我?
我的代码:
main.c
#include "chip.h"
#define NO_ROM_INSERTED 1
const int PIXEL_SIZE = 20;
const int CHIP_WIDTH = 64;
const int CHIP_HEIGHT = 32;
const int SCREEN_WIDTH = CHIP_WIDTH * PIXEL_SIZE;
const int SCREEN_HEIGHT = CHIP_HEIGHT * PIXEL_SIZE;
int main(int argc, char **argv)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
SDL_Event event;
int quit = 0;
Chip *chip = (Chip*)malloc(sizeof(Chip));
chipInitialize(chip);
chip->gfx[23] = 0x01;
/*Checks if a ROM file is inserted by an argument*/
if(argc < 2)
{
printf("Error, no Rom inserted");
return NO_ROM_INSERTED;
}
else
{
printf("\n%s loaded into memory\n", argv[argc-1]);
}
loadProgramInMemory(chip, "./Roms/TETRIS");
if(!init(window, renderer, SCREEN_WIDTH, SCREEN_HEIGHT))
{
printf( "Failed to initialize!\n" );
}
else
{
while(!quit)
{
while(SDL_PollEvent(&event) != 0)
{
if(event.type == SDL_QUIT)
{
quit = 1;
}
}
// Clear screen
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
SDL_RenderClear(renderer);
for(int i = 0; i < CHIP_HEIGHT; i++)
{
for(int j = 0; j < CHIP_WIDTH; j++)
{
if(chip->gfx[i * CHIP_WIDTH + j] > 0x00) //Translates the one dimensional gfx to two dimensional screen
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0x00, 0xFF);
SDL_Rect fillRect = {CHIP_WIDTH * i, CHIP_HEIGHT * j, PIXEL_SIZE, PIXEL_SIZE};
SDL_RenderFillRect(renderer, &fillRect);
}
}
}
// Update screen
SDL_RenderPresent(renderer);
}
}
close(window, renderer);
free(chip);
return 0;
}
chip.h
#include "window.h"
typedef struct chip{
unsigned char memory[4096];
unsigned short opcode;
unsigned short pc;
unsigned short stack[16];
unsigned short sp;
unsigned char gfx[64 * 32];
unsigned char V[16];
unsigned short I;
unsigned char delayTimer;
unsigned char soundTimer;
}Chip;
void chipInitialize(Chip *chip);
void loadFontInMemory(Chip *chip);
void loadProgramInMemory(Chip *chip, char *program);
chip.c
#include "chip.h"
void chipInitialize(Chip *chip)
{
chip->pc = 0x200; // Set program counter to 0x200
chip->opcode = 0x0000; // Reset current opcode
chip->I = 0x0000; // Reset index register
chip->sp = 0x0000; // Reset stack pointer
chip->delayTimer = 0x00; // Reset delay timer
chip->soundTimer = 0x00; // Reset sound timer
for(int i = 0; i < 64 * 32; i++) // Reset the graphics
chip->gfx[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset the stack
chip->stack[i] = 0x0000;
for(int i = 0; i < 4069; i++) // Reset memory
chip->memory[i] = 0x00;
for(int i = 0; i < 16; i++) // Reset registers
chip->V[i] = 0x00;
loadFontInMemory(chip); // Loads the font-set into memory
}
void loadProgramInMemory(Chip *chip, char *program)
{
int bufferSize = 0xFFF - 0x200; // Size of the memory which is reserved for the program
unsigned char buffer[bufferSize];
FILE *ptr;
ptr = fopen(program, "rb");
fread(buffer, bufferSize, 1, ptr);
for(int i = 0; i < bufferSize; i++)
chip->memory[i + 512] = buffer[i]; // Reads in the program and stores it in memory at location 0x200 or 512
}
void loadFontInMemory(Chip *chip)
{
// Zero // Six // C
chip->memory[0x000] = 0xF0; chip->memory[0x01E] = 0xF0; chip->memory[0x03C] = 0xF0;
chip->memory[0x001] = 0x90; chip->memory[0x01F] = 0x80; chip->memory[0x03D] = 0x80;
chip->memory[0x002] = 0x90; chip->memory[0x020] = 0xF0; chip->memory[0x03E] = 0x80;
chip->memory[0x003] = 0x90; chip->memory[0x021] = 0x90; chip->memory[0x03F] = 0x80;
chip->memory[0x004] = 0xF0; chip->memory[0x022] = 0xF0; chip->memory[0x040] = 0xF0;
// One // Seven // D
chip->memory[0x005] = 0x20; chip->memory[0x023] = 0xF0; chip->memory[0x041] = 0xE0;
chip->memory[0x006] = 0x60; chip->memory[0x024] = 0x10; chip->memory[0x042] = 0x90;
chip->memory[0x007] = 0x20; chip->memory[0x025] = 0x20; chip->memory[0x043] = 0x90;
chip->memory[0x008] = 0x20; chip->memory[0x026] = 0x40; chip->memory[0x044] = 0x90;
chip->memory[0x009] = 0x70; chip->memory[0x027] = 0x40; chip->memory[0x045] = 0xE0;
// Two // Eight // E
chip->memory[0x00A] = 0xF0; chip->memory[0x028] = 0xF0; chip->memory[0x046] = 0xF0;
chip->memory[0x00B] = 0x10; chip->memory[0x029] = 0x90; chip->memory[0x047] = 0x80;
chip->memory[0x00C] = 0xF0; chip->memory[0x02A] = 0xF0; chip->memory[0x048] = 0xF0;
chip->memory[0x00D] = 0x80; chip->memory[0x02B] = 0x90; chip->memory[0x049] = 0x80;
chip->memory[0x00E] = 0xF0; chip->memory[0x02C] = 0xF0; chip->memory[0x04A] = 0xF0;
// Three // Nine // F
chip->memory[0x00F] = 0xF0; chip->memory[0x02D] = 0xF0; chip->memory[0x04B] = 0xF0;
chip->memory[0x010] = 0x10; chip->memory[0x02E] = 0x90; chip->memory[0x04C] = 0x80;
chip->memory[0x011] = 0xF0; chip->memory[0x02F] = 0xF0; chip->memory[0x04D] = 0xF0;
chip->memory[0x012] = 0x10; chip->memory[0x030] = 0x10; chip->memory[0x04E] = 0x80;
chip->memory[0x013] = 0xF0; chip->memory[0x031] = 0xF0; chip->memory[0x04F] = 0x80;
// Four // A
chip->memory[0x014] = 0x90; chip->memory[0x032] = 0xF0;
chip->memory[0x015] = 0x90; chip->memory[0x033] = 0x90;
chip->memory[0x016] = 0xF0; chip->memory[0x034] = 0xF0;
chip->memory[0x017] = 0x10; chip->memory[0x035] = 0x90;
chip->memory[0x018] = 0x10; chip->memory[0x036] = 0x90;
// Five // B
chip->memory[0x019] = 0xF0; chip->memory[0x037] = 0xE0;
chip->memory[0x01A] = 0x80; chip->memory[0x038] = 0x90;
chip->memory[0x01B] = 0xF0; chip->memory[0x039] = 0xE0;
chip->memory[0x01C] = 0x10; chip->memory[0x03A] = 0x90;
chip->memory[0x01D] = 0xF0; chip->memory[0x03B] = 0xE0;
}
window.h
#include <SDL2/SDL.h>
#include <stdio.h>
#include <stdlib.h>
int init(SDL_Window *window, SDL_Renderer* renderer, const
int width, const int height);
void close(SDL_Window *window, SDL_Renderer* renderer);
window.c
#include "window.h"
int init(SDL_Window *window, SDL_Renderer *renderer, const
int width, const int height)
{
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
return success;
}
void close(SDL_Window *window, SDL_Renderer* renderer)
{
//Destroy window
SDL_DestroyWindow( window );
window = NULL;
SDL_DestroyRenderer(renderer);
renderer = NULL;
//Quit SDL subsystems
SDL_Quit();
}
生成文件
OBJS = main.c chip.c window.c
OBJ_NAME = Emulator
all : $(OBJS)
gcc $(OBJS) -IC:\code\SDL2\i686-w64-mingw32\include -LC:\code\SDL2\i686-w64-mingw32\lib -w -Wl,-subsystem,console -lmingw32 -lSDL2main -lSDL2 -o $(OBJ_NAME)
让我从一个建议开始 - 如果您对答案完全感兴趣,请不要让回答您的问题变得比需要的更难。想想它在其他人看来的样子——一些大量的代码,似乎没有绘制任何东西的问题;为什么这个例子必须有 6 个文件?为什么它依赖于我们没有的外部文件,因此实际上无法验证?当然,仅使用 init 和 render 就可以将其缩减为 30 行单个文件 - 实际上,SDL2 的任何 "hello world" 都可以。当它有效而您的代码无效时 - 您开始检查有什么不同。
现在回答你的问题。你不能从你的主循环中提取任何东西,因为你的 window
和 renderer
这里是 NULL - 它被初始化为 NULL 并且从未设置为任何其他东西。看来您对函数参数的工作方式有误解 - 在 C 中,函数参数是按值传递的,并且对该值的任何修改都是对本地函数副本进行的。当您传递一个 int 时,函数会获取该 int 的副本,并且不会推回任何更改。如果传递 SDL_Window*
,则传递该指针的 value(在您的情况下,NULL
);当您执行 SDL_CreateWindow
时,您将其分配给局部变量,并且再次无法 return 将其返回给调用者,它保持为 NULL。因此,您所有的渲染调用都将 NULL 作为渲染器传递,这自然不是有效的渲染器。
同样的事情出现在你的 close
- 你试图将传递的副本重置为 NULL,但这没有任何意义,因为你不能修改外部值,只能修改函数本地副本。
编程 类 经常教导有 "pass by value" 和 "pass by reference",我想这是混淆的根源。我宁愿说 C 中没有按引用传递,你总是传递值,但指针也是一个值。为了能够修改数据,我们将指针传递给该数据;要改变 int,您可以传递 int*
,但要改变 SDL_Window*
,您需要获得指向 that 指针的指针 - SDL_Window**
。看看 SDL 本身是如何做到的:https://wiki.libsdl.org/SDL_CreateWindowAndRenderer .
所以,简而言之 - 让你的 init
变成 int init(SDL_Window **window, SDL_Renderer** renderer, int width, int height);
(你在这里也不需要 const int
,因为这些是宽度和高度的副本),并且相应地修改其代码。并在调用后检查 window
和 renderer
的值(调试器、调试 printf、if(window==NULL)
一切正常)。 init
可能类似于
int init(SDL_Window **owindow, SDL_Renderer **orenderer,
int width, int height)
{
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
//Initialization flag
int success = 1;
//Initialize SDL
if( SDL_Init(SDL_INIT_VIDEO) < 0)
{
printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
//Create window
window = SDL_CreateWindow( "Chip-8 Emulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN );
if( window == NULL )
{
printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError());
success = 0;
}
else
{
renderer = SDL_CreateRenderer(window, -1, 0);
if(renderer == NULL)
{
printf( "Renderer could not be created! SDL Error: %s\n", SDL_GetError() );
success = 0;
}
else
{
SDL_SetRenderDrawColor(renderer, 0xFF, 0x00, 0xFF, 0xFF);
}
}
}
*owindow = window;
*orenderer = renderer;
return success;
}
当然调用init
必须修改为init(&window, &renderer, SCREEN_WIDTH, SCREEN_HEIGHT)
。
虽然我们正在做这件事,但还有两件事:
头文件应该有 include guards 否则如果你多次(直接或间接)包含它会导致问题。
永远不要调用你的函数
close
。它会(没有任何问题)在 linux/UNIX 系统上崩溃。考虑另一个未被广泛操作系统保留的名称。