On Saturday, 9 June 2018 at 03:14:13 UTC, cc wrote:
On Saturday, 9 June 2018 at 03:07:39 UTC, cc wrote:
I've put together a simplified test program here (124KB):

Here is a pastebin of the D source file updated with some additional comments at the end with the callback class definitions from the original header files
https://pastebin.com/M8hDXt6L

The proper bare minimum signature for call result callback is
------------------
extern(C++) abstract class CCallbackBase {
  abstract void Run( void *pvParam ) { writeln("Run()"); }
abstract void Run( void *pvParam, bool bIOFailure, SteamAPICall_t hSteamAPICall ); final int GetICallback() { return m_iCallback; } // this is actually optional
  abstract int GetCallbackSizeBytes();
 protected:
uint8 m_nCallbackFlags; // probably can be left for some specific use cases
  int m_iCallback;
}
------------------
and the rest templates and stuff is purely for C++ convenience. Run(void*, bool, SteamAPICall_t) is what actually called for call result, then CallResult<> template overrides it to call appropriate pointer member in class with void (T::fun)(Data*, bool bIOFailure) signature. You can mimic it on D side, or just ignore and make own.

There is one catch however, for it to be called flags should be equal 1, and iCallback must match struct enum, like NumberOfCurrentPlayers_t.k_iCallback for GetNumberOfCurrentPlayers()


However steam devs decided to shield actual pointer and return pointer sized integer when C API is used(or they just screw up?). Anyway, the pointers for subsystems returned by context calls on C++ API and mirrored C API calls are different, but they also have some mechanism for filtering this stuff, that way both integer handle and pointer calls the same underlying implementation, but C API call again is shielded so setting up CallResult and CCallback are ignored.


So my solution was just to make simple wrapper around C++ context calls and pass that real pointer to D side.

------------------- C++ code
// build as static library & link with your project
#ifdef _WIN32
// sorry, I just hardcoded it...
#pragma comment (lib, "steam_api64.lib")
#define _CRT_SECURE_NO_WARNINGS 1
#endif
  #include "public/steam/steam_api.h"
#ifdef _WIN32
#define _CRT_SECURE_NO_WARNINGS 1
#endif

extern "C" void* D_GetSteamUserStats()
{
  return SteamUserStats();
}

------------------- D code
// yes, I messed up with the signature to avoid casting, this may or may not be dangerous
extern(C) ISteamUserStats D_GetSteamUserStats();


This of course involves making C++ wrapper, but I don't really see other ways because they inlined everything ...

Reply via email to