Steam Input在我调用GetAnalogActionData时引发SEGFAULT。

huangapple go评论73阅读模式
英文:

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] is 319124578728929405
  • AnalogControls is 1
  • GameControls is 1

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 &lt;SDL2/SDL.h&gt;
#include &lt;steam/steam_api.h&gt;

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, &quot;Failed to initialize Steam API!&quot;);
        return 1;
    }
    // Initialize Steam Input
    if (!SteamInput()-&gt;Init(false)) {
        SDL_LogCritical(SDL_LOG_CATEGORY_INPUT, &quot;Failed to initialize Steam Input!&quot;);
        return 1;
    }

    {
        int res = SDL_Init(SDL_INIT_EVERYTHING);
        if (res &lt; 0) {
            SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, &quot;Failed to initialize SDL: %s&quot;, SDL_GetError());
            return res;
        }
    }

    window = SDL_CreateWindow(&quot;&gt;:(&quot;, 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, &quot;Failed to create window: %s&quot;, SDL_GetError());
        return 1;
    }

    renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
    if (renderer == nullptr) {
        SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, &quot;Failed to create renderer: %s&quot;, SDL_GetError());
        return 1;
    }

    SDL_Log(&quot;initialized&quot;);

    return 0;
}

void shutdown() {
    SDL_Log(&quot;shutting down&quot;);
    SDL_Quit();
    SteamAPI_Shutdown();
    SDL_Log(&quot;goodnight&quot;);
}

void tick() {
    SDL_Event ev;
    while (SDL_PollEvent(&amp;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(&quot;Button %s %s\n&quot;, buttonName, (ev.cbutton.state ? &quot;DOWN&quot; : &quot;UP&quot;));
                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()-&gt;GetAnalogActionHandle (&quot;AnalogControls&quot;);
    InputActionSetHandle_t GameControls = SteamInput()-&gt;GetActionSetHandle(&quot;GameControls&quot;);
    InputHandle_t controllers[STEAM_INPUT_MAX_COUNT]{};
    SteamInput()-&gt;GetConnectedControllers(controllers);
    SteamInput()-&gt;ActivateActionSet(controllers[0], GameControls);
    InputAnalogActionData_t data = SteamInput()-&gt;GetAnalogActionData(controllers[0], AnalogControls);
    printf(&quot;data: { %f, %f }\n&quot;, 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, &amp;rect);

    SDL_RenderPresent(renderer);
#ifdef NDEBUG
    GLenum err = glGetError();
    if (err != 0) SDL_LogError(SDL_LOG_CATEGORY_VIDEO, &quot;%x %s&quot;, err, glewGetErrorString(err));
#endif
}

int main(int argc, char* argv[]) {
    SDL_Log(&quot;running&quot;);
#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] is 319124578728929405
  • AnalogControls is 1
  • GameControls is 1

I'm developing using the default Spacewar appid, here's my IGA file (game_actions_480.vdf):

&quot;In Game Actions&quot;
{
&quot;actions&quot;
{
&quot;GameControls&quot;
{
&quot;title&quot;					&quot;#Set_GameControls&quot;
&quot;StickPadGyro&quot;
{
&quot;AnalogControls&quot;
{
&quot;title&quot;			&quot;#Action_AnalogControls&quot;
&quot;input_mode&quot;	&quot;joystick_move&quot;
}
}
&quot;Button&quot;
{
&quot;jump&quot;	&quot;#Action_Jump&quot;
}
}
&quot;MenuControls&quot;
{
&quot;title&quot;					&quot;#Set_MenuControls&quot;
&quot;Button&quot;
{
&quot;menu_up&quot;		&quot;#Action_MenuUp&quot;
&quot;menu_down&quot;		&quot;#Action_MenuDown&quot;
&quot;menu_left&quot;		&quot;#Action_MenuLeft&quot;
&quot;menu_right&quot;	&quot;#Action_MenuRight&quot;
&quot;menu_select&quot;	&quot;#Action_MenuSelect&quot;
&quot;menu_cancel&quot;	&quot;#Action_MenuCancel&quot;
}
}
}
&quot;localization&quot;
{
&quot;english&quot;
{
&quot;Title_Config1&quot;		&quot;Officially Configurated Configuration&quot;
&quot;Description_Config1&quot;	&quot;sdalskdjaksjda.&quot;
&quot;Set_GameControls&quot;			&quot;In-Game Controls&quot;
&quot;Set_MenuControls&quot;			&quot;Menu Controls&quot;
&quot;Action_AnalogControls&quot; 	&quot;Analog Controls&quot;
&quot;Action_Jump&quot;				&quot;Jump&quot;
&quot;Action_MenuUp&quot;				&quot;Menu Up&quot;
&quot;Action_MenuDown&quot;			&quot;Menu Down&quot;
&quot;Action_MenuLeft&quot;			&quot;Menu Left&quot;
&quot;Action_MenuRight&quot;			&quot;Menu Right&quot;
&quot;Action_MenuSelect&quot;			&quot;Menu Select&quot;
&quot;Action_MenuCancel&quot;			&quot;Menu Cancel&quot;
}
}
}

答案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.

huangapple
  • 本文由 发表于 2023年6月6日 09:26:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410890.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定