英文:
Steam Input causes SEGFAULT whenever I call GetAnalogActionData
问题
I'm making a game using SDL2, with controller support through Steamworks, and my program SEGFAULTs whenever GetAnalogActionData is called.
I'm compiling with MinGW g++ through MSYS2, using Steamworks API version 157.
I know I should store the handles once, but since it segfaults the second I try and read from the data, it never gets read again. I just want to figure out why this isn't working.
#include <SDL2/SDL.h>
#include <steam/steam_api.h>
SDL_Window *window;
SDL_Renderer *renderer;
bool isRunning = true;
using namespace std;
int init() {
// Initialize Steam API
if (!SteamAPI_Init()) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize Steam API!");
return 1;
}
// Initialize Steam Input
if (!SteamInput()->Init(false)) {
SDL_LogCritical(SDL_LOG_CATEGORY_INPUT, "Failed to initialize Steam Input!");
return 1;
}
{
int res = SDL_Init(SDL_INIT_EVERYTHING);
if (res < 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL: %s", SDL_GetError());
return res;
}
}
window = SDL_CreateWindow(">:(>", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
if (window == nullptr) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to create window: %s", SDL_GetError());
return 1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == nullptr) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to create renderer: %s", SDL_GetError());
return 1;
}
SDL_Log("initialized");
return 0;
}
void shutdown() {
SDL_Log("shutting down");
SDL_Quit();
SteamAPI_Shutdown();
SDL_Log("goodnight");
}
void tick() {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_WINDOWEVENT:
// fallthrough if event is closing the window
if (ev.window.event != SDL_WINDOWEVENT_CLOSE) { break; }
case SDL_QUIT: {
isRunning = false;
return;
break;
}
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP: {
const char* buttonName = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)ev.cbutton.button);
printf("Button %s %s\n", buttonName, (ev.cbutton.state ? "DOWN" : "UP"));
break;
}
}
}
SteamAPI_RunCallbacks();
SDL_SetRenderDrawColor(renderer, 0.f, 0.f, 0.f, 0.f);
SDL_RenderClear(renderer);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
#ifdef USE_STEAM
SteamAPI_RunCallbacks();
#endif // USE_STEAM
// render
SDL_Rect rect = {100, 100, 480, 480 };
InputAnalogActionHandle_t AnalogControls = SteamInput()->GetAnalogActionHandle ("AnalogControls");
InputActionSetHandle_t GameControls = SteamInput()->GetActionSetHandle("GameControls");
InputHandle_t controllers[STEAM_INPUT_MAX_COUNT]{};
SteamInput()->GetConnectedControllers(controllers);
SteamInput()->ActivateActionSet(controllers[0], GameControls);
InputAnalogActionData_t data = SteamInput()->GetAnalogActionData(controllers[0], AnalogControls);
printf("data: { %f, %f }\n", data.x, data.y);
SDL_SetRenderDrawColor(renderer, uint8_t(data.x * float(0xFF)), uint8_t(data.y * float(0xFF)), 0, SDL_ALPHA_OPAQUE);
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
#ifdef NDEBUG
GLenum err = glGetError();
if (err != 0) SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "%x %s", err, glewGetErrorString(err));
#endif
}
int main(int argc, char* argv[]) {
SDL_Log("running");
#ifdef NDEBUG
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
#endif
{
int i = init();
if (i) return i;
}
while (isRunning) tick();
shutdown();
return 0;
}
The debugger is giving me my values:
controllers[0]
is319124578728929405
AnalogControls
is1
GameControls
is1
I'm developing using the default Spacewar appid, here's my IGA file (game_actions_480.vdf
):
"In Game Actions"
{
"actions"
{
"GameControls"
{
"title" "#Set_GameControls"
"StickPadGyro"
{
"AnalogControls"
{
"title" "#Action_AnalogControls"
"input_mode" "joystick_move"
}
}
"Button"
{
"jump" "#Action_Jump"
}
}
"MenuControls"
{
"title" "#Set_MenuControls"
"Button"
{
"menu_up" "#Action_MenuUp"
"menu_down" "#Action_MenuDown"
"menu_left" "#Action_MenuLeft"
"menu_right" "#Action_MenuRight"
"menu_select" "#Action_MenuSelect"
"menu_cancel" "#Action_MenuCancel"
}
}
}
"localization"
{
"english"
{
"Title_Config1" "Officially Configurated Configuration"
"Description_Config1" "sdalskdjaksjda."
"Set_GameControls" "In-Game Controls"
"Set_MenuControls" "Menu Controls"
"Action_AnalogControls" "Analog Controls"
"Action_Jump" "Jump"
"Action_MenuUp" "Menu Up"
"Action_MenuDown" "Menu Down"
"Action_MenuLeft" "Menu Left"
"Action_MenuRight" "Menu Right"
"Action_MenuSelect" "Menu Select"
"Action_MenuCancel" "Menu Cancel"
}
}
}
(Note: I've corrected the HTML encoding issues in your original code.)
英文:
I'm making a game using SDL2, with controller support through Steamworks, and my program SEGFAULTs whenever GetAnalogActionData is called.
I'm compiling with MinGW g++ through MSYS2, using Steamworks API version 157.
I know I should store the handles once, but since it segfaults the second I try and read from the data, it never gets read again. I just want to figure out why this isn't working.
#include <SDL2/SDL.h>
#include <steam/steam_api.h>
SDL_Window *window;
SDL_Renderer *renderer;
bool isRunning = true;
using namespace std;
int init() {
// Initialize Steam API
if (!SteamAPI_Init()) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize Steam API!");
return 1;
}
// Initialize Steam Input
if (!SteamInput()->Init(false)) {
SDL_LogCritical(SDL_LOG_CATEGORY_INPUT, "Failed to initialize Steam Input!");
return 1;
}
{
int res = SDL_Init(SDL_INIT_EVERYTHING);
if (res < 0) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to initialize SDL: %s", SDL_GetError());
return res;
}
}
window = SDL_CreateWindow(">:(", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 640, SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
if (window == nullptr) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to create window: %s", SDL_GetError());
return 1;
}
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (renderer == nullptr) {
SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to create renderer: %s", SDL_GetError());
return 1;
}
SDL_Log("initialized");
return 0;
}
void shutdown() {
SDL_Log("shutting down");
SDL_Quit();
SteamAPI_Shutdown();
SDL_Log("goodnight");
}
void tick() {
SDL_Event ev;
while (SDL_PollEvent(&ev)) {
switch (ev.type) {
case SDL_WINDOWEVENT:
// fallthrough if event is closing the window
if (ev.window.event != SDL_WINDOWEVENT_CLOSE) { break; }
case SDL_QUIT: {
isRunning = false;
return;
break;
}
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP: {
const char* buttonName = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)ev.cbutton.button);
printf("Button %s %s\n", buttonName, (ev.cbutton.state ? "DOWN" : "UP"));
break;
}
}
}
SteamAPI_RunCallbacks();
SDL_SetRenderDrawColor(renderer, 0.f, 0.f, 0.f, 0.f);
SDL_RenderClear(renderer);
SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
#ifdef USE_STEAM
SteamAPI_RunCallbacks();
#endif // USE_STEAM
// render
SDL_Rect rect = {100, 100, 480, 480 };
InputAnalogActionHandle_t AnalogControls = SteamInput()->GetAnalogActionHandle ("AnalogControls");
InputActionSetHandle_t GameControls = SteamInput()->GetActionSetHandle("GameControls");
InputHandle_t controllers[STEAM_INPUT_MAX_COUNT]{};
SteamInput()->GetConnectedControllers(controllers);
SteamInput()->ActivateActionSet(controllers[0], GameControls);
InputAnalogActionData_t data = SteamInput()->GetAnalogActionData(controllers[0], AnalogControls);
printf("data: { %f, %f }\n", data.x, data.y);
SDL_SetRenderDrawColor(renderer, uint8_t(data.x * float(0xFF)), uint8_t(data.y * float(0xFF)), 0, SDL_ALPHA_OPAQUE);
SDL_RenderFillRect(renderer, &rect);
SDL_RenderPresent(renderer);
#ifdef NDEBUG
GLenum err = glGetError();
if (err != 0) SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "%x %s", err, glewGetErrorString(err));
#endif
}
int main(int argc, char* argv[]) {
SDL_Log("running");
#ifdef NDEBUG
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
#endif
{
int i = init();
if (i) return i;
}
while (isRunning) tick();
shutdown();
return 0;
}
The debugger is giving me my values:
controllers[0]
is319124578728929405
AnalogControls
is1
GameControls
is1
I'm developing using the default Spacewar appid, here's my IGA file (game_actions_480.vdf
):
"In Game Actions"
{
"actions"
{
"GameControls"
{
"title" "#Set_GameControls"
"StickPadGyro"
{
"AnalogControls"
{
"title" "#Action_AnalogControls"
"input_mode" "joystick_move"
}
}
"Button"
{
"jump" "#Action_Jump"
}
}
"MenuControls"
{
"title" "#Set_MenuControls"
"Button"
{
"menu_up" "#Action_MenuUp"
"menu_down" "#Action_MenuDown"
"menu_left" "#Action_MenuLeft"
"menu_right" "#Action_MenuRight"
"menu_select" "#Action_MenuSelect"
"menu_cancel" "#Action_MenuCancel"
}
}
}
"localization"
{
"english"
{
"Title_Config1" "Officially Configurated Configuration"
"Description_Config1" "sdalskdjaksjda."
"Set_GameControls" "In-Game Controls"
"Set_MenuControls" "Menu Controls"
"Action_AnalogControls" "Analog Controls"
"Action_Jump" "Jump"
"Action_MenuUp" "Menu Up"
"Action_MenuDown" "Menu Down"
"Action_MenuLeft" "Menu Left"
"Action_MenuRight" "Menu Right"
"Action_MenuSelect" "Menu Select"
"Action_MenuCancel" "Menu Cancel"
}
}
}
答案1
得分: 0
这真的很不幸;我能够通过使用Clang++(MSVC后端)而不是g++来解决这个问题。我需要进一步研究这个问题,但目前来说,使用MSVC“解决”了这个问题。我真的需要使用g++,所以任何建议都会受到欢迎。
英文:
This is really unfortunate; I was able to solve the problem by using Clang++ (MSVC backend) instead of g++. I'm going to need to look into this further, but for now, using MSVC ""solves"" the issue. I really need to use g++, so any advice is appreciated.
答案2
得分: 0
这有点晚了,但最终我弄明白了,然后忘了回答自己的问题!
事实证明(通过阅读文档我找到了答案),Steamworks 提供了一个叫做 steam_api_flat.h
的替代标头,用于与其他编译器/语言一起使用的 C API。我的代码看起来像这样:
InputDigitalActionData_t data = SteamAPI_ISteamInput_GetDigitalActionData(SteamAPI_SteamInput(), activeSteamControllerHandle, h);
希望这对某人有所帮助。
英文:
This is a bit late, but I eventually figured it out and forgot to answer my own question!
As it turns out (I figured this out by reading the docs) Steamworks provides an alternative header, called steam_api_flat.h
, providing a C API for use with other compilers/languages. My code looks like this:
InputDigitalActionData_t data = SteamAPI_ISteamInput_GetDigitalActionData(SteamAPI_SteamInput(), activeSteamControllerHandle, h);
Hopefully this helps somebody out.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论