Windows 尽管根目录中有正确的 DLL,但可执行文件无法启动
Windows executable fails to start despite having correct DLLs in root directory
我的超简单2D游戏冒险依赖sdl-2 and sdl-ttf。
编译后目录如下
Caventure.exe
libfreetype-6.dll
notomono-regular.ttf
SDL2.dll
SDL2_ttf.dll
zlib1.dll
我使用的是 Microsoft Visual Studio 2015。我一直在关注 Lazy Foo's tutorials on building with Windows,但即使按照这些步骤操作,它也不起作用。这是我所做的:
- 将编译器链接到 x64 中的包含和库目录。
- 链接库。
- 已将库复制到
C:\Windows\SysWOW64
。
- 包括
<Windows.h>
。
- 使用兼容模式。
- 在 Visual Studio IDE 中对其进行了测试,包括调试器。
当我打开它时,它立即关闭,没有 return 任何错误。
这是主要的源文件:
#include <stdio.h>
#include <stdexcept>
#include <Windows.h>
#include <SDL.h>
#include <SDL_ttf.h>
#include "TextMenu.h"
#include "TextBox.h"
#include "Graphics.h"
#include "Event.h"
// Screen dimensions, constants
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// 600 for ground, 280 for output, 20 for input
Graphics Global;
Event Loop;
void Init(Graphics& Global)
{
if (SDL_Init(SDL_INIT_VIDEO) > 0)
{
throw(::std::runtime_error("SDL failed to initialise! ERROR: "));
}
Global.Window = SDL_CreateWindow("Caventure",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (Global.Window == NULL)
{
throw(::std::runtime_error("Window failed to initialise! ERROR: "));
}
Global.ScreenSurface = SDL_GetWindowSurface(Global.Window);
if (Global.ScreenSurface == NULL)
{
throw(::std::runtime_error("Surface failed to initialise! ERROR: "));
}
Global.Renderer = SDL_CreateRenderer(Global.Window, -1, 0);
if (Global.Renderer == NULL)
{
throw(::std::runtime_error("Renderer could not be initialised! ERROR: "));
}
if (TTF_Init() > 0)
{
throw(::std::runtime_error("TTF could not be initialised! ERROR: "));
}
}
void UpdateMedia(Graphics& Global)
{
SDL_GetWindowSize(Global.Window, &Global.width, &Global.height);
// Set geomtry dimensions, apart from rcTextInput.
Global.rcGround = { 0, 0, Global.width, (Global.height / 3) * 2 };
Global.rcTextOutput = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
Global.rcTextOutputGrd = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
Global.SpriteDefaultX = Global.width / 2;
Global.SpriteDefaultY = Global.height / 2;
};
void LoadMedia(Graphics& Global)
{
UpdateMedia(Global);
Global.rcSprite = { Global.SpriteDefaultX, Global.SpriteDefaultY, 4, 4 };
Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
if (Global.Font == NULL)
{
throw(::std::runtime_error("Font failed to load! ERROR: "));
}
SDL_SetTextInputRect(&Global.rcTextInput);
}
void InputLoop(Graphics& Global, Event& Loop)
{
if (Loop.event.type == SDL_QUIT)
{
Loop.bQuit = true;
}
else if (Loop.event.type == SDL_KEYDOWN)
{
// Sprite movement
switch (Loop.event.key.keysym.sym)
{
case SDLK_UP:
Global.rcSprite.y -= 5;
break;
case SDLK_DOWN:
Global.rcSprite.y += 5;
break;
case SDLK_LEFT:
Global.rcSprite.x -= 5;
break;
case SDLK_RIGHT:
Global.rcSprite.x += 5;
break;
}
// Backspace handler
if (Loop.event.key.keysym.sym == SDLK_BACKSPACE && Loop.InputText.length() > 0)
{
Loop.InputText.pop_back();
if (Loop.InputText.length() == 0)
{
Loop.InputText = " ";
}
}
// Creates new line of text
else if (Loop.event.key.keysym.sym == SDLK_RETURN && Loop.InputText.length() != 0 && Loop.InputText != " ")
{
Global.Menu.NewBox(Loop.InputText);
Loop.bRenderText = true;
Loop.InputText = " ";
}
}
else if (Loop.event.type == SDL_TEXTINPUT)
{
Loop.InputText += Loop.event.text.text;
}
}
void RenderLoop(Graphics& Global, Event& Loop)
{
UpdateMedia(Global);
// Renders sprite movement
if (Global.rcSprite.x < 0 || Global.rcSprite.y < 0 || Global.rcSprite.y > Global.rcGround.h || Global.rcSprite.x > Global.rcGround.w)
{
Global.rcSprite.x = Global.SpriteDefaultX;
Global.rcSprite.y = Global.SpriteDefaultY;
}
// Sets background to black
SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(Global.Renderer);
// Renders background of sprite to black
SDL_RenderFillRect(Global.Renderer, &Global.rcGround);
SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcGround);
// Renders background of text box to grey
SDL_SetRenderDrawColor(Global.Renderer, 0x40, 0x40, 0x40, 0x40);
SDL_RenderFillRect(Global.Renderer, &Global.rcTextOutputGrd);
SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcTextOutputGrd);
SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
// Renders text input
Global.TextInput.Render(Global.Renderer, Global.Font, Loop.InputText.c_str(), Global.TextColor);
Global.rcTextInput = { 0, Global.height - 20, Global.TextInput.GetWidth(), Global.TextInput.GetHeight() };
SDL_RenderCopy(Global.Renderer, Global.TextInput.GetTexture(), NULL, &Global.rcTextInput);
// Renders text output
if (Loop.bRenderText)
{
Global.Menu.Update(Global.Renderer, Global.Font, Global.TextColor, Global.rcTextOutput);
}
SDL_RenderSetClipRect(Global.Renderer, NULL);
// Renders text box background edges white
SDL_SetRenderDrawColor(Global.Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderDrawLine(Global.Renderer, 0, (Global.height / 3) * 2, Global.width, (Global.height / 3) * 2);
SDL_RenderDrawLine(Global.Renderer, 0, Global.height - 20, Global.width, Global.height - 20);
// Renders sprite
SDL_RenderFillRect(Global.Renderer, &Global.rcSprite);
SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcSprite);
// Presents render
SDL_RenderPresent(Global.Renderer);
}
void Quit(Graphics& Global)
{
// Deallocate memory
SDL_DestroyWindow(Global.Window);
SDL_DestroyRenderer(Global.Renderer);
TTF_CloseFont(Global.Font);
Global.Window = NULL;
Global.Renderer = NULL;
Global.Font = NULL;
// Quit SDL subsystems
TTF_Quit();
SDL_Quit();
}
int main(int argc, char *argv[])
{
try
{
Init(Global);
LoadMedia(Global);
SDL_StartTextInput();
while (!Loop.bQuit)
{
while (SDL_PollEvent(&Loop.event) != 0)
{
InputLoop(Global, Loop);
RenderLoop(Global, Loop);
}
}
SDL_StopTextInput();
}
catch (std::runtime_error const& msg)
{
printf("%s", msg.what());
if (SDL_GetError() != NULL)
{
printf("%s", SDL_GetError());
}
else if (TTF_GetError() != NULL)
{
printf("%s", TTF_GetError());
}
else
{
printf("%s", "NULL");
}
Quit(Global);
return EXIT_FAILURE;
}
Quit(Global);
return EXIT_SUCCESS;
}
四点建议:
- 检查 windows 事件日志。
- 运行 它在调试器中。
- 从 windows 命令行启动它。
- 添加日志记录。
发生错误时,程序
向控制台打印一条消息,但是没有控制台,所以消息无处可去,然后
立即退出,即使有控制台也瞬间消失
如果您想从 GUI Windows 程序实际报告错误,您必须等待足够长的时间让用户看到错误。对于 SDL,SDL_ShowSimpleMessageBox 是一个不错的选择。
我插入了SDL_Log()
after every successful initialisation to find the error. I used gdb来监控日志
原来是
Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
出错了。
将其替换为简单的
Global.Font = TTF_OpenFont("notomono-regular.ttf", 14);
更正了错误。
我的超简单2D游戏冒险依赖sdl-2 and sdl-ttf。
编译后目录如下
Caventure.exe
libfreetype-6.dll
notomono-regular.ttf
SDL2.dll
SDL2_ttf.dll
zlib1.dll
我使用的是 Microsoft Visual Studio 2015。我一直在关注 Lazy Foo's tutorials on building with Windows,但即使按照这些步骤操作,它也不起作用。这是我所做的:
- 将编译器链接到 x64 中的包含和库目录。
- 链接库。
- 已将库复制到
C:\Windows\SysWOW64
。 - 包括
<Windows.h>
。 - 使用兼容模式。
- 在 Visual Studio IDE 中对其进行了测试,包括调试器。
当我打开它时,它立即关闭,没有 return 任何错误。
这是主要的源文件:
#include <stdio.h>
#include <stdexcept>
#include <Windows.h>
#include <SDL.h>
#include <SDL_ttf.h>
#include "TextMenu.h"
#include "TextBox.h"
#include "Graphics.h"
#include "Event.h"
// Screen dimensions, constants
#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600
// 600 for ground, 280 for output, 20 for input
Graphics Global;
Event Loop;
void Init(Graphics& Global)
{
if (SDL_Init(SDL_INIT_VIDEO) > 0)
{
throw(::std::runtime_error("SDL failed to initialise! ERROR: "));
}
Global.Window = SDL_CreateWindow("Caventure",
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
SCREEN_WIDTH,
SCREEN_HEIGHT,
SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
if (Global.Window == NULL)
{
throw(::std::runtime_error("Window failed to initialise! ERROR: "));
}
Global.ScreenSurface = SDL_GetWindowSurface(Global.Window);
if (Global.ScreenSurface == NULL)
{
throw(::std::runtime_error("Surface failed to initialise! ERROR: "));
}
Global.Renderer = SDL_CreateRenderer(Global.Window, -1, 0);
if (Global.Renderer == NULL)
{
throw(::std::runtime_error("Renderer could not be initialised! ERROR: "));
}
if (TTF_Init() > 0)
{
throw(::std::runtime_error("TTF could not be initialised! ERROR: "));
}
}
void UpdateMedia(Graphics& Global)
{
SDL_GetWindowSize(Global.Window, &Global.width, &Global.height);
// Set geomtry dimensions, apart from rcTextInput.
Global.rcGround = { 0, 0, Global.width, (Global.height / 3) * 2 };
Global.rcTextOutput = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
Global.rcTextOutputGrd = { 0, (Global.height / 3) * 2, Global.width, Global.height - 40 };
Global.SpriteDefaultX = Global.width / 2;
Global.SpriteDefaultY = Global.height / 2;
};
void LoadMedia(Graphics& Global)
{
UpdateMedia(Global);
Global.rcSprite = { Global.SpriteDefaultX, Global.SpriteDefaultY, 4, 4 };
Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
if (Global.Font == NULL)
{
throw(::std::runtime_error("Font failed to load! ERROR: "));
}
SDL_SetTextInputRect(&Global.rcTextInput);
}
void InputLoop(Graphics& Global, Event& Loop)
{
if (Loop.event.type == SDL_QUIT)
{
Loop.bQuit = true;
}
else if (Loop.event.type == SDL_KEYDOWN)
{
// Sprite movement
switch (Loop.event.key.keysym.sym)
{
case SDLK_UP:
Global.rcSprite.y -= 5;
break;
case SDLK_DOWN:
Global.rcSprite.y += 5;
break;
case SDLK_LEFT:
Global.rcSprite.x -= 5;
break;
case SDLK_RIGHT:
Global.rcSprite.x += 5;
break;
}
// Backspace handler
if (Loop.event.key.keysym.sym == SDLK_BACKSPACE && Loop.InputText.length() > 0)
{
Loop.InputText.pop_back();
if (Loop.InputText.length() == 0)
{
Loop.InputText = " ";
}
}
// Creates new line of text
else if (Loop.event.key.keysym.sym == SDLK_RETURN && Loop.InputText.length() != 0 && Loop.InputText != " ")
{
Global.Menu.NewBox(Loop.InputText);
Loop.bRenderText = true;
Loop.InputText = " ";
}
}
else if (Loop.event.type == SDL_TEXTINPUT)
{
Loop.InputText += Loop.event.text.text;
}
}
void RenderLoop(Graphics& Global, Event& Loop)
{
UpdateMedia(Global);
// Renders sprite movement
if (Global.rcSprite.x < 0 || Global.rcSprite.y < 0 || Global.rcSprite.y > Global.rcGround.h || Global.rcSprite.x > Global.rcGround.w)
{
Global.rcSprite.x = Global.SpriteDefaultX;
Global.rcSprite.y = Global.SpriteDefaultY;
}
// Sets background to black
SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
SDL_RenderClear(Global.Renderer);
// Renders background of sprite to black
SDL_RenderFillRect(Global.Renderer, &Global.rcGround);
SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcGround);
// Renders background of text box to grey
SDL_SetRenderDrawColor(Global.Renderer, 0x40, 0x40, 0x40, 0x40);
SDL_RenderFillRect(Global.Renderer, &Global.rcTextOutputGrd);
SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcTextOutputGrd);
SDL_SetRenderDrawColor(Global.Renderer, 0x00, 0x00, 0x00, 0x00);
// Renders text input
Global.TextInput.Render(Global.Renderer, Global.Font, Loop.InputText.c_str(), Global.TextColor);
Global.rcTextInput = { 0, Global.height - 20, Global.TextInput.GetWidth(), Global.TextInput.GetHeight() };
SDL_RenderCopy(Global.Renderer, Global.TextInput.GetTexture(), NULL, &Global.rcTextInput);
// Renders text output
if (Loop.bRenderText)
{
Global.Menu.Update(Global.Renderer, Global.Font, Global.TextColor, Global.rcTextOutput);
}
SDL_RenderSetClipRect(Global.Renderer, NULL);
// Renders text box background edges white
SDL_SetRenderDrawColor(Global.Renderer, 0xFF, 0xFF, 0xFF, 0xFF);
SDL_RenderDrawLine(Global.Renderer, 0, (Global.height / 3) * 2, Global.width, (Global.height / 3) * 2);
SDL_RenderDrawLine(Global.Renderer, 0, Global.height - 20, Global.width, Global.height - 20);
// Renders sprite
SDL_RenderFillRect(Global.Renderer, &Global.rcSprite);
SDL_BlitSurface(Global.CurrentSurface, NULL, Global.ScreenSurface, &Global.rcSprite);
// Presents render
SDL_RenderPresent(Global.Renderer);
}
void Quit(Graphics& Global)
{
// Deallocate memory
SDL_DestroyWindow(Global.Window);
SDL_DestroyRenderer(Global.Renderer);
TTF_CloseFont(Global.Font);
Global.Window = NULL;
Global.Renderer = NULL;
Global.Font = NULL;
// Quit SDL subsystems
TTF_Quit();
SDL_Quit();
}
int main(int argc, char *argv[])
{
try
{
Init(Global);
LoadMedia(Global);
SDL_StartTextInput();
while (!Loop.bQuit)
{
while (SDL_PollEvent(&Loop.event) != 0)
{
InputLoop(Global, Loop);
RenderLoop(Global, Loop);
}
}
SDL_StopTextInput();
}
catch (std::runtime_error const& msg)
{
printf("%s", msg.what());
if (SDL_GetError() != NULL)
{
printf("%s", SDL_GetError());
}
else if (TTF_GetError() != NULL)
{
printf("%s", TTF_GetError());
}
else
{
printf("%s", "NULL");
}
Quit(Global);
return EXIT_FAILURE;
}
Quit(Global);
return EXIT_SUCCESS;
}
四点建议:
- 检查 windows 事件日志。
- 运行 它在调试器中。
- 从 windows 命令行启动它。
- 添加日志记录。
发生错误时,程序
向控制台打印一条消息,但是没有控制台,所以消息无处可去,然后
立即退出,即使有控制台也瞬间消失
如果您想从 GUI Windows 程序实际报告错误,您必须等待足够长的时间让用户看到错误。对于 SDL,SDL_ShowSimpleMessageBox 是一个不错的选择。
我插入了SDL_Log()
after every successful initialisation to find the error. I used gdb来监控日志
原来是
Global.Font = TTF_OpenFont("src/graphics/resources/notomono-regular.ttf", 14);
出错了。
将其替换为简单的
Global.Font = TTF_OpenFont("notomono-regular.ttf", 14);
更正了错误。