diff --git a/exe/GarnetRs/Wrapped.hs b/exe/GarnetRs/Wrapped.hs index ee80ce0..e98a2c0 100644 --- a/exe/GarnetRs/Wrapped.hs +++ b/exe/GarnetRs/Wrapped.hs @@ -29,8 +29,8 @@ data Shape | Rectangle CDouble CDouble convertShape :: Shape -> Raw.Shape convertShape = \case - Circle r -> Raw.Shape (Raw.Shape_Tag 0) $ Raw.set_shape_body_circle $ Raw.Circle_Body r - Rectangle w h -> Raw.Shape (Raw.Shape_Tag 1) $ Raw.set_shape_body_rectangle $ Raw.Rectangle_Body w h + Circle r -> Raw.Shape Raw.Circle $ Raw.set_shape_body_circle $ Raw.Circle_Body r + Rectangle w h -> Raw.Shape Raw.Rectangle $ Raw.set_shape_body_rectangle $ Raw.Rectangle_Body w h hello :: ByteString -> IO () hello s = useAsCString s $ Raw.hello . unsafeFromPtr diff --git a/generate-bindings b/generate-bindings index 10e240b..0e1ba05 100755 --- a/generate-bindings +++ b/generate-bindings @@ -36,56 +36,11 @@ echo " Raw header written to $HEADER" # --- Step 3: Patch the header for hs-bindgen compatibility --- # -# Two patches are needed, both due to hs-bindgen limitations with cbindgen's -# output for #[repr(C, u8)] tagged enums: -# -# 1. cbindgen emits: enum Shape_Tag { Circle, Rectangle, }; -# typedef uint8_t Shape_Tag; -# hs-bindgen needs: typedef uint8_t Shape_Tag; -# #define Circle 0 -# #define Rectangle 1 -# See: no upstream issue yet for hs-bindgen -# -# 2. cbindgen emits: union { ... }; (anonymous) -# hs-bindgen needs: union { ... } body; (named) -# See: https://github.com/well-typed/hs-bindgen/issues/1649 +# cbindgen emits: union { ... }; (anonymous) +# hs-bindgen needs: union { ... } body; (named) +# See: https://github.com/well-typed/hs-bindgen/issues/1649 echo "=== Patching header ===" awk ' -# State machine for enum->typedef+define transformation -/^enum [A-Za-z_][A-Za-z0-9_]* \{$/ { - in_enum = 1 - enum_name = $2 - variant_count = 0 - delete variants - next -} -in_enum && /^\};$/ { - # Next line should be: typedef ; - in_enum = 0 - pending_enum = 1 - next -} -in_enum { - # Collect variant names (strip trailing comma and whitespace) - v = $0 - gsub(/^[[:space:]]+/, "", v) - gsub(/,[[:space:]]*$/, "", v) - if (v != "") { - variants[variant_count] = v - variant_count++ - } - next -} -pending_enum && /^typedef [A-Za-z0-9_]+ / { - # Emit: typedef ; then #define for each variant - print $0 - for (i = 0; i < variant_count; i++) { - printf "#define %s %d\n", variants[i], i - } - pending_enum = 0 - next -} - # Name anonymous unions: }; at end of union block inside struct -> } body; /^ \};$/ && saw_union { print " } body;" diff --git a/generated/GarnetRs.hs b/generated/GarnetRs.hs index 07ba5b8..dd7470d 100644 --- a/generated/GarnetRs.hs +++ b/generated/GarnetRs.hs @@ -3,12 +3,12 @@ {-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE DuplicateRecordFields #-} -{-# LANGUAGE ExplicitForAll #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MagicHash #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE NoImplicitPrelude #-} +{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} @@ -19,8 +19,7 @@ module GarnetRs where import qualified Data.Array.Byte -import qualified Data.Bits as Bits -import qualified Data.Ix as Ix +import qualified Data.List.NonEmpty import qualified Data.Primitive.Types import qualified Data.Proxy import qualified Foreign as F @@ -28,16 +27,16 @@ import qualified Foreign.C as FC import qualified GHC.Generics import qualified GHC.Ptr as Ptr import qualified GHC.Records +import qualified HsBindgen.Runtime.CEnum import qualified HsBindgen.Runtime.HasCField -import qualified HsBindgen.Runtime.Internal.Bitfield import qualified HsBindgen.Runtime.Internal.ByteArray import qualified HsBindgen.Runtime.Internal.HasFFIType import qualified HsBindgen.Runtime.Internal.SizedByteArray import qualified HsBindgen.Runtime.LibC import qualified HsBindgen.Runtime.Marshal -import Data.Bits (FiniteBits) +import qualified Text.Read import HsBindgen.Runtime.Internal.TypeEquality (TyEq) -import Prelude ((<*>), (>>), Bounded, Enum, Eq, Int, Integral, Num, Ord, Read, Real, Show, pure) +import Prelude ((<*>), (>>), Eq, Int, Ord, Read, Show, pure, showsPrec) {-| __C declaration:__ @struct T@ @@ -114,34 +113,86 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType T) "b") getField = HsBindgen.Runtime.HasCField.fromPtr (Data.Proxy.Proxy @"b") -{-| __C declaration:__ @Shape_Tag@ +{-| __C declaration:__ @enum Shape_Tag@ - __defined at:__ @garnet_rs.h 11:17@ + __defined at:__ @garnet_rs.h 11:14@ __exported by:__ @garnet_rs.h@ -} newtype Shape_Tag = Shape_Tag - { unwrap :: HsBindgen.Runtime.LibC.Word8 + { unwrap :: FC.CUInt } deriving stock (GHC.Generics.Generic) - deriving stock (Eq, Ord, Read, Show) - deriving newtype - ( HsBindgen.Runtime.Marshal.StaticSize - , HsBindgen.Runtime.Marshal.ReadRaw - , HsBindgen.Runtime.Marshal.WriteRaw - , F.Storable - , HsBindgen.Runtime.Internal.HasFFIType.HasFFIType - , Data.Primitive.Types.Prim - , HsBindgen.Runtime.Internal.Bitfield.Bitfield - , Bits.Bits - , Bounded - , Enum - , FiniteBits - , Integral - , Ix.Ix - , Num - , Real - ) + deriving stock (Eq, Ord) + deriving newtype (HsBindgen.Runtime.Internal.HasFFIType.HasFFIType) + +instance HsBindgen.Runtime.Marshal.StaticSize Shape_Tag where + + staticSizeOf = \_ -> (4 :: Int) + + staticAlignment = \_ -> (4 :: Int) + +instance HsBindgen.Runtime.Marshal.ReadRaw Shape_Tag where + + readRaw = + \ptr0 -> + pure Shape_Tag + <*> HsBindgen.Runtime.Marshal.readRawByteOff ptr0 (0 :: Int) + +instance HsBindgen.Runtime.Marshal.WriteRaw Shape_Tag where + + writeRaw = + \ptr0 -> + \s1 -> + case s1 of + Shape_Tag unwrap2 -> + HsBindgen.Runtime.Marshal.writeRawByteOff ptr0 (0 :: Int) unwrap2 + +deriving via HsBindgen.Runtime.Marshal.EquivStorable Shape_Tag instance F.Storable Shape_Tag + +deriving via FC.CUInt instance Data.Primitive.Types.Prim Shape_Tag + +instance HsBindgen.Runtime.CEnum.CEnum Shape_Tag where + + type CEnumZ Shape_Tag = FC.CUInt + + toCEnum = Shape_Tag + + fromCEnum = GHC.Records.getField @"unwrap" + + declaredValues = + \_ -> + HsBindgen.Runtime.CEnum.declaredValuesFromList [ (0, Data.List.NonEmpty.singleton "Circle") + , (1, Data.List.NonEmpty.singleton "Rectangle") + ] + + showsUndeclared = + HsBindgen.Runtime.CEnum.showsWrappedUndeclared "Shape_Tag" + + readPrecUndeclared = + HsBindgen.Runtime.CEnum.readPrecWrappedUndeclared "Shape_Tag" + + isDeclared = HsBindgen.Runtime.CEnum.seqIsDeclared + + mkDeclared = HsBindgen.Runtime.CEnum.seqMkDeclared + +instance HsBindgen.Runtime.CEnum.SequentialCEnum Shape_Tag where + + minDeclaredValue = Circle + + maxDeclaredValue = Rectangle + +instance Show Shape_Tag where + + showsPrec = HsBindgen.Runtime.CEnum.shows + +instance Read Shape_Tag where + + readPrec = HsBindgen.Runtime.CEnum.readPrec + + readList = Text.Read.readListDefault + + readListPrec = Text.Read.readListPrecDefault instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Shape_Tag) "unwrap") ) => GHC.Records.HasField "unwrap" (Ptr.Ptr Shape_Tag) (Ptr.Ptr ty) where @@ -151,32 +202,31 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Shape_Tag) "unwrap") instance HsBindgen.Runtime.HasCField.HasCField Shape_Tag "unwrap" where - type CFieldType Shape_Tag "unwrap" = - HsBindgen.Runtime.LibC.Word8 + type CFieldType Shape_Tag "unwrap" = FC.CUInt offset# = \_ -> \_ -> 0 {-| __C declaration:__ @Circle@ - __defined at:__ @garnet_rs.h 12:9@ + __defined at:__ @garnet_rs.h 12:3@ __exported by:__ @garnet_rs.h@ -} -circle :: FC.CInt -circle = (0 :: FC.CInt) +pattern Circle :: Shape_Tag +pattern Circle = Shape_Tag 0 {-| __C declaration:__ @Rectangle@ - __defined at:__ @garnet_rs.h 13:9@ + __defined at:__ @garnet_rs.h 13:3@ __exported by:__ @garnet_rs.h@ -} -rectangle :: FC.CInt -rectangle = (1 :: FC.CInt) +pattern Rectangle :: Shape_Tag +pattern Rectangle = Shape_Tag 1 {-| __C declaration:__ @struct Circle_Body@ - __defined at:__ @garnet_rs.h 15:16@ + __defined at:__ @garnet_rs.h 16:16@ __exported by:__ @garnet_rs.h@ -} @@ -184,7 +234,7 @@ data Circle_Body = Circle_Body { radius :: FC.CDouble {- ^ __C declaration:__ @radius@ - __defined at:__ @garnet_rs.h 16:10@ + __defined at:__ @garnet_rs.h 17:10@ __exported by:__ @garnet_rs.h@ -} @@ -230,7 +280,7 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Circle_Body) "radius {-| __C declaration:__ @struct Rectangle_Body@ - __defined at:__ @garnet_rs.h 19:16@ + __defined at:__ @garnet_rs.h 20:16@ __exported by:__ @garnet_rs.h@ -} @@ -238,14 +288,14 @@ data Rectangle_Body = Rectangle_Body { width :: FC.CDouble {- ^ __C declaration:__ @width@ - __defined at:__ @garnet_rs.h 20:10@ + __defined at:__ @garnet_rs.h 21:10@ __exported by:__ @garnet_rs.h@ -} , height :: FC.CDouble {- ^ __C declaration:__ @height@ - __defined at:__ @garnet_rs.h 21:10@ + __defined at:__ @garnet_rs.h 22:10@ __exported by:__ @garnet_rs.h@ -} @@ -305,7 +355,7 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Rectangle_Body) "hei {-| __C declaration:__ @union \@Shape_body@ - __defined at:__ @garnet_rs.h 26:3@ + __defined at:__ @garnet_rs.h 27:3@ __exported by:__ @garnet_rs.h@ -} @@ -328,7 +378,7 @@ deriving via HsBindgen.Runtime.Marshal.EquivStorable Shape_body instance F.Stora __C declaration:__ @circle@ -__defined at:__ @garnet_rs.h 27:17@ +__defined at:__ @garnet_rs.h 28:17@ __exported by:__ @garnet_rs.h@ -} @@ -355,7 +405,7 @@ set_shape_body_circle = __C declaration:__ @rectangle@ -__defined at:__ @garnet_rs.h 28:20@ +__defined at:__ @garnet_rs.h 29:20@ __exported by:__ @garnet_rs.h@ -} @@ -403,7 +453,7 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Shape_body) "rectang {-| __C declaration:__ @struct Shape@ - __defined at:__ @garnet_rs.h 24:16@ + __defined at:__ @garnet_rs.h 25:16@ __exported by:__ @garnet_rs.h@ -} @@ -411,14 +461,14 @@ data Shape = Shape { tag :: Shape_Tag {- ^ __C declaration:__ @tag@ - __defined at:__ @garnet_rs.h 25:13@ + __defined at:__ @garnet_rs.h 26:13@ __exported by:__ @garnet_rs.h@ -} , body :: Shape_body {- ^ __C declaration:__ @body@ - __defined at:__ @garnet_rs.h 29:5@ + __defined at:__ @garnet_rs.h 30:5@ __exported by:__ @garnet_rs.h@ -} diff --git a/generated/GarnetRs/FunPtr.hs b/generated/GarnetRs/FunPtr.hs index 253311f..48f8e33 100644 --- a/generated/GarnetRs/FunPtr.hs +++ b/generated/GarnetRs/FunPtr.hs @@ -65,7 +65,7 @@ hs_bindgen_faf62265b53521d3 = {-# NOINLINE hello #-} {-| __C declaration:__ @hello@ - __defined at:__ @garnet_rs.h 32:6@ + __defined at:__ @garnet_rs.h 33:6@ __exported by:__ @garnet_rs.h@ -} @@ -85,7 +85,7 @@ hs_bindgen_0f8c37ef19b17a6d = {-# NOINLINE hello_struct #-} {-| __C declaration:__ @hello_struct@ - __defined at:__ @garnet_rs.h 34:6@ + __defined at:__ @garnet_rs.h 35:6@ __exported by:__ @garnet_rs.h@ -} @@ -105,7 +105,7 @@ hs_bindgen_287ff3ac660f333b = {-# NOINLINE hello_shape #-} {-| __C declaration:__ @hello_shape@ - __defined at:__ @garnet_rs.h 36:6@ + __defined at:__ @garnet_rs.h 37:6@ __exported by:__ @garnet_rs.h@ -} @@ -125,7 +125,7 @@ hs_bindgen_bbabdbe61cd1eeb2 = {-# NOINLINE add #-} {-| __C declaration:__ @add@ - __defined at:__ @garnet_rs.h 38:32@ + __defined at:__ @garnet_rs.h 39:32@ __exported by:__ @garnet_rs.h@ -} diff --git a/generated/GarnetRs/Safe.hs b/generated/GarnetRs/Safe.hs index 40b04fa..7fb9bad 100644 --- a/generated/GarnetRs/Safe.hs +++ b/generated/GarnetRs/Safe.hs @@ -60,7 +60,7 @@ hs_bindgen_433ea2a26af4e593 = {-| __C declaration:__ @hello@ - __defined at:__ @garnet_rs.h 32:6@ + __defined at:__ @garnet_rs.h 33:6@ __exported by:__ @garnet_rs.h@ -} @@ -84,7 +84,7 @@ hs_bindgen_51157946af5519c9 = {-| __C declaration:__ @hello_struct@ - __defined at:__ @garnet_rs.h 34:6@ + __defined at:__ @garnet_rs.h 35:6@ __exported by:__ @garnet_rs.h@ -} @@ -110,7 +110,7 @@ hs_bindgen_7de06f1fd827ca60 = {-| __C declaration:__ @hello_shape@ - __defined at:__ @garnet_rs.h 36:6@ + __defined at:__ @garnet_rs.h 37:6@ __exported by:__ @garnet_rs.h@ -} @@ -142,7 +142,7 @@ hs_bindgen_1c0c71fa74c428a9 = __C declaration:__ @add@ -__defined at:__ @garnet_rs.h 38:32@ +__defined at:__ @garnet_rs.h 39:32@ __exported by:__ @garnet_rs.h@ -} diff --git a/generated/GarnetRs/Unsafe.hs b/generated/GarnetRs/Unsafe.hs index 0fa12e0..25d7ee9 100644 --- a/generated/GarnetRs/Unsafe.hs +++ b/generated/GarnetRs/Unsafe.hs @@ -60,7 +60,7 @@ hs_bindgen_2dfe97662a4d6377 = {-| __C declaration:__ @hello@ - __defined at:__ @garnet_rs.h 32:6@ + __defined at:__ @garnet_rs.h 33:6@ __exported by:__ @garnet_rs.h@ -} @@ -84,7 +84,7 @@ hs_bindgen_29d823ada2bc7302 = {-| __C declaration:__ @hello_struct@ - __defined at:__ @garnet_rs.h 34:6@ + __defined at:__ @garnet_rs.h 35:6@ __exported by:__ @garnet_rs.h@ -} @@ -110,7 +110,7 @@ hs_bindgen_b3f40a03f07eaa85 = {-| __C declaration:__ @hello_shape@ - __defined at:__ @garnet_rs.h 36:6@ + __defined at:__ @garnet_rs.h 37:6@ __exported by:__ @garnet_rs.h@ -} @@ -142,7 +142,7 @@ hs_bindgen_20eb651f0a8faf48 = __C declaration:__ @add@ -__defined at:__ @garnet_rs.h 38:32@ +__defined at:__ @garnet_rs.h 39:32@ __exported by:__ @garnet_rs.h@ -} diff --git a/rust/garnet_rs.h b/rust/garnet_rs.h index 3bef3e6..88f8332 100644 --- a/rust/garnet_rs.h +++ b/rust/garnet_rs.h @@ -8,9 +8,10 @@ typedef struct T { uint8_t b; } T; -typedef uint8_t Shape_Tag; -#define Circle 0 -#define Rectangle 1 +typedef enum Shape_Tag { + Circle, + Rectangle, +} Shape_Tag; typedef struct Circle_Body { double radius; diff --git a/rust/lib.rs b/rust/lib.rs index 3e2f64f..c0906e5 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -22,7 +22,7 @@ extern "C" fn hello_struct(t: T) -> () { say_hello(&format!("{:?}", t)) } -#[repr(C, u8)] +#[repr(C)] #[derive(Debug)] enum Shape { Circle { radius: f64 },