Search code examples
pythonctypessteamsteam-web-apisteamworks-api

STEAMWORKS API - Python ctypes


I am trying to do stats, leaderboards, achievements, etc. with my Python app.

I know I'm connecting to the DLL proper, but it seems no matter how I try to call the functions. I get an error saying they don't exist.

If someone knows how to do this without ctypes and a library instead or something. I'm very open to any solution.

Can someone please help?

steam_api.SteamAPI_SteamUserStats.restype = ctypes.POINTER(ISteamUserStats)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: function 'SteamAPI_SteamUserStats' not found

.....

import os
import platform
import ctypes

# Determine system architecture (32-bit or 64-bit)
is_64bits = platform.architecture()[0] == '64bit'

# Set path to the steam_api DLL based on system architecture
if is_64bits:
    steam_api_path = os.path.abspath('./steamworks/redistributable_bin/win64/steam_api64.dll')
else:
    steam_api_path = os.path.abspath('./steamworks/redistributable_bin/win32/steam_api.dll')

# Add directory containing steam_api DLL to PATH environment variable
os.environ['PATH'] = os.path.dirname(steam_api_path) + os.pathsep + os.environ.get('PATH', '')

# Load steam_api DLL
steam_api = ctypes.CDLL(steam_api_path)

# Define ISteamUserStats interface structure
class ISteamUserStats(ctypes.Structure):
    _fields_ = []

steam_api.SteamAPI_InitFlat()
# Define function prototypes
steam_api.SteamAPI_SteamUserStats.restype = ctypes.POINTER(ISteamUserStats)
steam_api.SteamAPI_ISteamUserStats_RequestCurrentStats.argtypes = [ctypes.POINTER(ISteamUserStats)]
steam_api.SteamAPI_ISteamUserStats_RequestCurrentStats.restype = ctypes.c_bool

# Initialize Steam API
def steam_init():
    if not steam_api.SteamAPI_InitFlat():
        raise RuntimeError('Steam API Init failed')

# Shutdown Steam API
def steam_shutdown():
    steam_api.SteamAPI_Shutdown()

# Request current stats function
def request_current_stats():
    user_stats = steam_api.SteamAPI_SteamUserStats()
    result = steam_api.SteamAPI_ISteamUserStats_RequestCurrentStats(user_stats)
    if not result:
        error_code = ctypes.get_last_error()
        raise RuntimeError(f'RequestCurrentStats failed with error code: {error_code}')

# Example usage
if __name__ == '__main__':
    try:
        steam_init()
        print("Steam API Initialized successfully.")

        request_current_stats()
        print("Current stats requested successfully.")

    except Exception as e:
        print(f"An error occurred: {str(e)}")

    finally:
        steam_shutdown()
        print("Steam API Shutdown.")

Solution

  • steam_api_flat.h contains the following:

    // A versioned accessor is exported by the library
    S_API ISteamUserStats *SteamAPI_SteamUserStats_v012();
    // Inline, unversioned accessor to get the current version.  Essentially the same as SteamUserStats(), but using this ensures that you are using a matching library.
    inline ISteamUserStats *SteamAPI_SteamUserStats() { return SteamAPI_SteamUserStats_v012(); }
    

    So SteamAPI_SteamUserStats isn't actually part of the DLL. Since you're not using the C header file, you need to use SteamAPI_SteamUserStats_v012 instead.

    You'll probably run into more issues like this if you keep going the way you are. https://partner.steamgames.com/doc/sdk/api#thirdparty has more information on this, and in particular it mentions the existence of SteamworksPy.