// SPDX-License-Identifier: BSD-3-Clause // // Thin C shim for the Box3D Haskell bindings. // // The Box3D public API passes and returns several small structs *by value*, // which GHC's FFI cannot express in general. Ids are exempt: they are // integer-only structs of at most 8 bytes, and on the supported 64-bit ABIs // (x86-64 SysV and Win64, AArch64) they travel in a general-purpose register // exactly like a uint32_t/uint64_t, so the Haskell side imports id-only // functions directly with word-sized newtypes (see the _Static_asserts in // box3d_shim.c). Everything else — float structs, which travel in vector // registers or by hidden reference, and the config defs — is wrapped here // into a pointer-based form. The naming convention is hs_; // a value that was returned by value is written through a trailing // out-pointer, and a non-id value that was passed by value is taken through // a const in-pointer. #pragma once #include "box3d/box3d.h" // base.h ----------------------------------------------------------------- // b3Version b3GetVersion(void) void hs_b3GetVersion(b3Version* out); // math_functions.h ------------------------------------------------------- bool hs_b3IsValidVec3(const b3Vec3* a); bool hs_b3IsValidQuat(const b3Quat* q); bool hs_b3IsValidTransform(const b3Transform* a); bool hs_b3IsValidMatrix3(const b3Matrix3* a); bool hs_b3IsValidAABB(const b3AABB* a); bool hs_b3IsValidPlane(const b3Plane* a); // b3CosSin b3ComputeCosSin(float radians) void hs_b3ComputeCosSin(float radians, b3CosSin* out); // b3Quat b3ComputeQuatBetweenUnitVectors(b3Vec3 v1, b3Vec3 v2) void hs_b3ComputeQuatBetweenUnitVectors(const b3Vec3* v1, const b3Vec3* v2, b3Quat* out); // types.h: default definition constructors -------------------------------- void hs_b3DefaultWorldDef(b3WorldDef* out); void hs_b3DefaultBodyDef(b3BodyDef* out); void hs_b3DefaultShapeDef(b3ShapeDef* out); void hs_b3DefaultFilter(b3Filter* out); void hs_b3DefaultSurfaceMaterial(b3SurfaceMaterial* out); void hs_b3DefaultQueryFilter(b3QueryFilter* out); void hs_b3DefaultExplosionDef(b3ExplosionDef* out); // The world / body by-value accessors now live in the generated // box3d_gen_shim.{h,c} (hsg_ prefix). This file keeps only the shims backing // the hand-written scaffolding (base.h, math_functions.h, the *Def defaults). // types.h: joint definition defaults --------------------------------------- void hs_b3DefaultDistanceJointDef(b3DistanceJointDef* out); void hs_b3DefaultMotorJointDef(b3MotorJointDef* out); void hs_b3DefaultParallelJointDef(b3ParallelJointDef* out); void hs_b3DefaultPrismaticJointDef(b3PrismaticJointDef* out); void hs_b3DefaultRevoluteJointDef(b3RevoluteJointDef* out); void hs_b3DefaultSphericalJointDef(b3SphericalJointDef* out); void hs_b3DefaultWeldJointDef(b3WeldJointDef* out); void hs_b3DefaultWheelJointDef(b3WheelJointDef* out); void hs_b3DefaultFilterJointDef(b3FilterJointDef* out); // Callback trampolines: fixed C functions with the engine's callback // signatures. The context must point at an hs_b3Closure whose fn is a // Haskell-wrapped function of the pointer-argument variant of the signature // and whose context is the user context it receives. typedef struct hs_b3Closure { void* fn; void* context; } hs_b3Closure; float hs_b3CastResultTrampoline(b3ShapeId shapeId, b3Pos point, b3Vec3 normal, float fraction, uint64_t userMaterialId, int triangleIndex, int childIndex, void* context); bool hs_b3PreSolveTrampoline(b3ShapeId shapeIdA, b3ShapeId shapeIdB, b3Pos point, b3Vec3 normal, void* context); bool hs_b3MeshQueryTrampoline(b3Vec3 a, b3Vec3 b, b3Vec3 c, int triangleIndex, void* context);