I am developing my first game for steam, and I am trying to get the basic steam flat file to work in python. The library that did this seems to be dead (steamworkspy), and is not trivial to set up in the first place.
I have written code that wraps the redistributable dlls in python as shown below.
import os
os.environ["SteamAppId"] = "480"
os.environ["SteamDebug"] = "1"
import ctypes
import platform
import sys
import time
def check_steam_restart(dll_path, app_id):
steam = ctypes.windll.LoadLibrary(dll_path)
func = steam.SteamAPI_RestartAppIfNecessary
func.argtypes = [ctypes.c_uint32]
func.restype = ctypes.c_bool
result = func(ctypes.c_uint32(app_id))
print(f"SteamAPI_RestartAppIfNecessary returned: {result}")
if result:
print("Steam needs to relaunch the app through Steam — exiting...")
sys.exit(0)
class Steam:
def __init__(self):
self._dll = self._load_library()
self._initialize_functions()
def _check_symbol(self, symbol_name):
if not hasattr(self._dll, symbol_name):
raise Exception(f"Function '{symbol_name}' not found in Steamworks library.")
def _load_library(self):
"""Load the correct platform-specific Steamworks DLL."""
redistributable_bin_path = {
'Windows': {
'64bit': r'steamworks_sdk_162\sdk\redistributable_bin\win64\steam_api64.dll',
'32bit': r'steamworks_sdk_162\sdk\redistributable_bin\steam_api.dll'
},
'Linux': {
'64bit': r'steamworks_sdk_162/sdk/redistributable_bin/linux64/libsteam_api.so',
'32bit': r'steamworks_sdk_162/sdk/redistributable_bin/linux32/libsteam_api.so'
}
}
system = platform.system()
architecture = platform.architecture()[0]
if system not in redistributable_bin_path or architecture not in redistributable_bin_path[system]:
raise OSError(f'Unsupported platform or architecture: {system} {architecture}')
library_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
redistributable_bin_path[system][architecture]
)
if not os.path.exists(library_path):
raise FileNotFoundError(f"Steamworks library not found at {library_path}")
print(f"Steamworks library located: {library_path}")
if system == 'Windows':
return ctypes.windll.LoadLibrary(library_path)
else:
return ctypes.CDLL(library_path)
def _initialize_functions(self):
# Step 2: Initialize Steam via InitFlat
if hasattr(self._dll, "SteamAPI_InitFlat"):
print("Using SteamAPI_InitFlat")
self._dll.SteamAPI_InitFlat.argtypes = []
self._dll.SteamAPI_InitFlat.restype = ctypes.c_bool
else:
raise Exception("SteamAPI_InitFlat not found in DLL")
# Step 3: Register Shutdown (for __exit__)
if hasattr(self._dll, "SteamAPI_Shutdown"):
self._dll.SteamAPI_Shutdown.argtypes = []
self._dll.SteamAPI_Shutdown.restype = None
else:
raise Exception("SteamAPI_Shutdown not found in DLL")
def __enter__(self):
# Optional: Check if Steam is running
if hasattr(self._dll, "SteamAPI_IsSteamRunning"):
self._dll.SteamAPI_IsSteamRunning.restype = ctypes.c_bool
running = self._dll.SteamAPI_IsSteamRunning()
print(f"Steam running: {running}")
print("Initializing Steam API via Flat...")
if not self._dll.SteamAPI_InitFlat():
raise Exception("SteamAPI_InitFlat failed")
print("Steam API initialized successfully.")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Shutting down Steam API...")
self._dll.SteamAPI_Shutdown()
if __name__ == "__main__":
try:
dll_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
r"steamworks_sdk_162\sdk\redistributable_bin\win64\steam_api64.dll"
)
app_id = int(os.environ["SteamAppId"])
print(f"Using App ID: {app_id}")
check_steam_restart(dll_path, app_id)
with Steam() as steam:
print("Steam API initialized successfully.")
# Debugging HSteamPipe and HSteamUser
# mod_manager = ModManager(steam._dll)
# print(f"HSteamPipe: {mod_manager._steam_pipe}")
# print(f"HSteamUser: {mod_manager._steam_user}")
# # Test ISteamUGC interface retrieval
# ugc_interface = mod_manager._ugc_interface
# print(f"ISteamUGC interface retrieved: {ugc_interface}")
except Exception as e:
print(f"Error: {e}")
However, this returns a very unhelpful error, usually something I see in memory management.
(venv) D:\97cweb\Documents\Projects\SimAntics\py-lua\simantics_SteamworksWrapper\simantics_SteamworksWrapper>python steam.py
Using App ID: 480
SteamAPI_RestartAppIfNecessary returned: False
Steamworks library located: D:\97cweb\Documents\Projects\SimAntics\py-lua\simantics_SteamworksWrapper\simantics_SteamworksWrapper\steamworks_sdk_162\sdk\redistributable_bin\win64\steam_api64.dll
Using SteamAPI_InitFlat
Steam running: True
Initializing Steam API via Flat...
Setting breakpad minidump AppID = 480
SteamInternal_SetMinidumpSteamID: Caching Steam ID: 76561198283721268 [API loaded no]
Error: exception: access violation writing 0x0000000000000001
Any help getting this to work is greatly appreciated. I did try google and the robot to get this to work as well, so just google it is not the answer.
Due to no responses, even with the max amount of point bait I could give, I was able to kick the compiler for steamworks-py hard enough to get it to work. This is nontrivial, and I wrote an entire blog post on it. https://yottarock.ca/51
This is to compile on windows 11
First you will need the proper terminal to compile on. To get this, copy the following into a terminal. What it does is downloads the Visual studio installer, and get the build tools installed for terminal. I pulled this from saikyun's github but as I don't trust anything to stay on the internet, here it is. To execute, paste and run. Accept the Visual Studio launch, and continue. It's huge, so it will take a while to download
Invoke-RestMethod -Uri https://aka.ms/vs/17/release/vs_buildtools.exe -OutFile vs_buildtools.exe
Start-Process -FilePath vs_buildtools.exe -ArgumentList "--add", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", "--add", "Microsoft.VisualStudio.Component.Windows10SDK.19041", "--norestart", "--passive", "--wait" -Wait -PassThru
Remove-Item vs_buildtools.exe
Once you have this, copy the git repository of steamworks-py. Do this however you want, I am still partial to the zip download, as I do not plan on pushing it back to them.
Once you get that unpacked in whatever surrounding directory you want, download the steam sdk from steamworks. As of this writing, the sdk is located in the right sidebar near the bottom.
Unpack/unzip the sdk. Now enter into it and locate the steam folder within "sdk\public" inside the steamworks folder. Cut it and paste it inside steamworks-py at "Steamworks-Py-master\library\sdk".
Inside the steamworks folder again, navigate to "sdk\redistributable_bin\win64". Cut and paste both the steam_api64.dll and steam_api64.lib into "Steamworks-Py-master\library"
Open a terminal. In the dropdown beside the terminal tab, select "Developer Command Prompt for VS <year>". Once it opens, navigate to the library folder within Steamworks-Py-master.
Paste and run the following command:
cl /D_USRDLL /D_WINDLL SteamworksPy.cpp steam_api64.lib /link /DLL /OUT:SteamworksPy64.dll
Let it execute.
Once it runs, inside the library folder, there will be a file called "SteamworksPy64.dll".
Now to make it into a pip installable library.
The following steps will make the folder structure match this:
SteamworksWrapper/
├── setup.py
├── pyproject.toml
├── MANIFEST.in
└── src/
└── steamworks/
├── __init__.py
├── util.py
├── enums.py
├── structs.py
├── SteamworksPy64.dll
├── steam_api64.dll
└── steam_appid.txt
To start, setup a new project structure like this:
SteamworksWrapper/
├── setup.py
├── pyproject.toml
├── MANIFEST.in
└── src/
Copy the SteamworksPy64.dll
, steam_api64.dll
, and steam_appid.txt
into the steamworks
folder. Then copy the entire steamworks
folder (containing all the .py
and .dll
files) into src/
.
Edit the setup.py script to the following:
from setuptools import setup, find_packages
setup(
name="steamworks",
version="0.1.0",
packages=find_packages(where="src"),
package_dir={"": "src"},
include_package_data=True,
package_data={"steamworks": ["*.dll", "*.txt"]},
)
pyproject.toml
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"
MANIFEST.in
recursive-include src/steamworks *.dll
With the terminal set to the environment you are building your game in (venv) navigate to SteamworksWrapper/
Run:
pip install -e .
It is now installed!
To call it, write the following:
from steamworks import STEAMWORKS
and everything will just work