Compare commits

..

13 Commits

Author SHA1 Message Date
George Thomas
569fae5d32 Move Haskell package to top level 2026-02-19 14:15:14 +00:00
George Thomas
dba9dbfc78 Rename Haskell.nix flake input 2026-02-19 14:11:45 +00:00
George Thomas
738315da88 Bump flake inputs 2026-02-19 14:11:45 +00:00
George Thomas
4606c040f8 Reformat 2026-02-19 14:11:45 +00:00
George Thomas
f539fe609a Refactor Nix flake inputs 2026-02-19 14:11:45 +00:00
George Thomas
577bc54ec4 Disable dead code warning for whole Rust file 2026-02-19 14:11:45 +00:00
George Thomas
ca87a67686 Call struct function with different arguments 2026-02-19 14:11:32 +00:00
George Thomas
e740db0a24 Create manual high level wrapper 2026-02-19 14:11:05 +00:00
George Thomas
7c988765fa Add Bash script dependencies to Nix shell 2026-02-19 13:57:14 +00:00
George Thomas
6a600f3aec Simplify use sites by passing by value 2026-02-19 13:57:14 +00:00
George Thomas
2e7770df7a Use ByteString 2026-02-19 13:57:14 +00:00
George Thomas
0f88ebe316 Add more complex data types 2026-02-19 13:57:14 +00:00
George Thomas
e434f0d4b0 Expose explicit C interface 2026-02-19 13:57:14 +00:00
11 changed files with 131 additions and 274 deletions

1
.gitignore vendored
View File

@ -1,4 +1,3 @@
dist* dist*
result result
target target
cabal.project.local*

View File

@ -1,5 +1,13 @@
packages: . packages: .
-- TODO a total hack
package garnet
extra-lib-dirs:
/home/gthomas/code/garnet/rust/target/release
/home/gthomas/code/garnet/rust/target/debug
extra-include-dirs:
/home/gthomas/code/garnet/rust
-- https://well-typed.com/blog/2026/02/hs-bindgen-alpha -- https://well-typed.com/blog/2026/02/hs-bindgen-alpha
-- Haskell.nix doesn't seem to like `tag: release-0.1-alpha`, which the blog post suggests -- Haskell.nix doesn't seem to like `tag: release-0.1-alpha`, which the blog post suggests
-- so we specify the equivalent commit SHAs manually instead -- so we specify the equivalent commit SHAs manually instead

View File

@ -6,7 +6,6 @@ module GarnetRs.Wrapped (
hello, hello,
helloStruct, helloStruct,
helloShape, helloShape,
add,
) where ) where
import Data.ByteString import Data.ByteString
@ -22,15 +21,15 @@ data T = T
, b :: Word8 , b :: Word8
} }
convertT :: T -> Raw.T convertT :: T -> Raw.T
convertT T{a, b} = Raw.T{a = fromBool a, b} convertT T{a, b} = Raw.T{a = CBool $ fromBool a, b}
data Shape data Shape
= Circle CDouble = Circle CDouble
| Rectangle CDouble CDouble | Rectangle CDouble CDouble
convertShape :: Shape -> Raw.Shape convertShape :: Shape -> Raw.Shape
convertShape = \case convertShape = \case
Circle r -> Raw.Shape Raw.Circle $ Raw.set_shape_body_circle $ Raw.Circle_Body r Circle r -> Raw.Shape (Raw.Shape_Tag 0) $ 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 Rectangle w h -> Raw.Shape (Raw.Shape_Tag 1) $ Raw.set_shape_body_rectangle $ Raw.Rectangle_Body w h
hello :: ByteString -> IO () hello :: ByteString -> IO ()
hello s = useAsCString s $ Raw.hello . unsafeFromPtr hello s = useAsCString s $ Raw.hello . unsafeFromPtr
@ -40,6 +39,3 @@ helloStruct = Raw.hello_struct . convertT
helloShape :: Shape -> IO () helloShape :: Shape -> IO ()
helloShape = Raw.hello_shape . convertShape helloShape = Raw.hello_shape . convertShape
add :: Int64 -> Int64 -> Int64
add = Raw.add

View File

@ -9,4 +9,3 @@ main = do
helloStruct T{a = False, b = maxBound} helloStruct T{a = False, b = maxBound}
helloShape $ Circle 3.14 helloShape $ Circle 3.14
helloShape $ Rectangle 10.0 5.0 helloShape $ Rectangle 10.0 5.0
putStrLn $ "3 + 4 = " <> show (add 3 4)

View File

@ -5,12 +5,7 @@ set -euo pipefail
# Generate Haskell FFI bindings from Rust source code. # Generate Haskell FFI bindings from Rust source code.
# #
# Pipeline: # Pipeline: cargo build -> cbindgen -> patch header -> hs-bindgen
# 1. cargo build - build the Rust static library
# 2. cbindgen - generate a C header from the Rust source
# 3. awk - patch the header for hs-bindgen compatibility
# 4. hs-bindgen-cli - generate Haskell FFI modules from the C header
# 5. cabal configure - point Cabal at the Rust build artifacts
# #
# Prerequisites: run inside the Nix dev shell (provides gcc, cabal, cbindgen, hs-bindgen-cli). # Prerequisites: run inside the Nix dev shell (provides gcc, cabal, cbindgen, hs-bindgen-cli).
@ -30,18 +25,59 @@ cbindgen \
--lang c \ --lang c \
--crate garnet-rs \ --crate garnet-rs \
--output "$HEADER" \ --output "$HEADER" \
--style tag \
"$RUST_DIR" "$RUST_DIR"
echo " Raw header written to $HEADER" echo " Raw header written to $HEADER"
# --- Step 3: Patch the header for hs-bindgen compatibility --- # --- Step 3: Patch the header for hs-bindgen compatibility ---
#
# cbindgen emits: union { ... }; (anonymous)
# hs-bindgen needs: union { ... } body; (named)
# See: https://github.com/well-typed/hs-bindgen/issues/1649
echo "=== Patching header ===" echo "=== Patching header ==="
# Two patches are needed:
#
# Patch 1: Replace cbindgen's enum pattern with typedef + #defines.
# cbindgen emits: enum Shape_Tag { Circle, Rectangle, }; typedef uint8_t Shape_Tag;
# hs-bindgen needs: typedef uint8_t Shape_Tag; #define Circle 0 ...
#
# Patch 2: Name anonymous unions inside structs.
# cbindgen emits: union { ... };
# hs-bindgen needs: union { ... } body;
awk ' 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 <type> <enum_name>;
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 <type> <name>; 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; # Name anonymous unions: }; at end of union block inside struct -> } body;
/^ \};$/ && saw_union { /^ \};$/ && saw_union {
print " } body;" print " } body;"
@ -58,11 +94,11 @@ awk '
echo " Patched header at $HEADER" echo " Patched header at $HEADER"
# --- Step 4: Derive system include paths for hs-bindgen's libclang --- # --- Step 4: Derive system include paths for hs-bindgen's libclang ---
# echo "=== Detecting system include paths ==="
# hs-bindgen uses libclang directly, which doesn't know about NixOS's # hs-bindgen uses libclang directly, which doesn't know about NixOS's
# non-standard include locations. We extract them from cpp -v and pass # non-standard include locations. We extract them from cpp -v and pass
# all of them — extra paths are harmless. # all of them — extra paths are harmless.
echo "=== Detecting system include paths ==="
CLANG_OPTIONS=() CLANG_OPTIONS=()
while IFS= read -r dir; do while IFS= read -r dir; do
CLANG_OPTIONS+=("--clang-option" "-isystem$dir") CLANG_OPTIONS+=("--clang-option" "-isystem$dir")
@ -86,16 +122,6 @@ hs-bindgen-cli preprocess \
"${CLANG_OPTIONS[@]}" \ "${CLANG_OPTIONS[@]}" \
-I "$RUST_DIR" "$HEADER_NAME" -I "$RUST_DIR" "$HEADER_NAME"
# --- Step 6: Configure Cabal ---
#
# Point Cabal at the Rust static library and C header. This writes
# cabal.project.local (gitignored) with absolute paths derived from
# the current working directory, avoiding hardcoded paths in cabal.project.
echo "=== Configuring Cabal ==="
cabal configure \
--extra-lib-dirs="$RUST_DIR/target/debug" \
--extra-include-dirs="$RUST_DIR"
echo "=== Done ===" echo "=== Done ==="
echo "Generated Haskell bindings in $HASKELL_DIR/generated/" echo "Generated Haskell bindings in $HASKELL_DIR/generated/"
echo "Run 'cabal run' to test." echo "Run 'cabal run' to test."

View File

@ -3,12 +3,12 @@
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DerivingVia #-} {-# LANGUAGE DerivingVia #-}
{-# LANGUAGE DuplicateRecordFields #-} {-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE ExplicitForAll #-}
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MagicHash #-} {-# LANGUAGE MagicHash #-}
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeFamilies #-}
@ -19,7 +19,8 @@
module GarnetRs where module GarnetRs where
import qualified Data.Array.Byte import qualified Data.Array.Byte
import qualified Data.List.NonEmpty import qualified Data.Bits as Bits
import qualified Data.Ix as Ix
import qualified Data.Primitive.Types import qualified Data.Primitive.Types
import qualified Data.Proxy import qualified Data.Proxy
import qualified Foreign as F import qualified Foreign as F
@ -27,20 +28,20 @@ import qualified Foreign.C as FC
import qualified GHC.Generics import qualified GHC.Generics
import qualified GHC.Ptr as Ptr import qualified GHC.Ptr as Ptr
import qualified GHC.Records import qualified GHC.Records
import qualified HsBindgen.Runtime.CEnum
import qualified HsBindgen.Runtime.HasCField import qualified HsBindgen.Runtime.HasCField
import qualified HsBindgen.Runtime.Internal.Bitfield
import qualified HsBindgen.Runtime.Internal.ByteArray import qualified HsBindgen.Runtime.Internal.ByteArray
import qualified HsBindgen.Runtime.Internal.HasFFIType import qualified HsBindgen.Runtime.Internal.HasFFIType
import qualified HsBindgen.Runtime.Internal.SizedByteArray import qualified HsBindgen.Runtime.Internal.SizedByteArray
import qualified HsBindgen.Runtime.LibC import qualified HsBindgen.Runtime.LibC
import qualified HsBindgen.Runtime.Marshal import qualified HsBindgen.Runtime.Marshal
import qualified Text.Read import Data.Bits (FiniteBits)
import HsBindgen.Runtime.Internal.TypeEquality (TyEq) import HsBindgen.Runtime.Internal.TypeEquality (TyEq)
import Prelude ((<*>), (>>), Eq, Int, Ord, Read, Show, pure, showsPrec) import Prelude ((<*>), (>>), Bounded, Enum, Eq, Int, Integral, Num, Ord, Read, Real, Show, pure)
{-| __C declaration:__ @struct T@ {-| __C declaration:__ @struct T@
__defined at:__ @garnet_rs.h 6:8@ __defined at:__ @garnet_rs.h 6:16@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -113,86 +114,34 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType T) "b")
getField = getField =
HsBindgen.Runtime.HasCField.fromPtr (Data.Proxy.Proxy @"b") HsBindgen.Runtime.HasCField.fromPtr (Data.Proxy.Proxy @"b")
{-| __C declaration:__ @enum Shape_Tag@ {-| __C declaration:__ @Shape_Tag@
__defined at:__ @garnet_rs.h 11:6@ __defined at:__ @garnet_rs.h 11:17@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
newtype Shape_Tag = Shape_Tag newtype Shape_Tag = Shape_Tag
{ unwrap :: FC.CUInt { unwrap :: HsBindgen.Runtime.LibC.Word8
} }
deriving stock (GHC.Generics.Generic) deriving stock (GHC.Generics.Generic)
deriving stock (Eq, Ord) deriving stock (Eq, Ord, Read, Show)
deriving newtype (HsBindgen.Runtime.Internal.HasFFIType.HasFFIType) deriving newtype
( HsBindgen.Runtime.Marshal.StaticSize
instance HsBindgen.Runtime.Marshal.StaticSize Shape_Tag where , HsBindgen.Runtime.Marshal.ReadRaw
, HsBindgen.Runtime.Marshal.WriteRaw
staticSizeOf = \_ -> (4 :: Int) , F.Storable
, HsBindgen.Runtime.Internal.HasFFIType.HasFFIType
staticAlignment = \_ -> (4 :: Int) , Data.Primitive.Types.Prim
, HsBindgen.Runtime.Internal.Bitfield.Bitfield
instance HsBindgen.Runtime.Marshal.ReadRaw Shape_Tag where , Bits.Bits
, Bounded
readRaw = , Enum
\ptr0 -> , FiniteBits
pure Shape_Tag , Integral
<*> HsBindgen.Runtime.Marshal.readRawByteOff ptr0 (0 :: Int) , Ix.Ix
, Num
instance HsBindgen.Runtime.Marshal.WriteRaw Shape_Tag where , Real
)
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") instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Shape_Tag) "unwrap")
) => GHC.Records.HasField "unwrap" (Ptr.Ptr Shape_Tag) (Ptr.Ptr ty) where ) => GHC.Records.HasField "unwrap" (Ptr.Ptr Shape_Tag) (Ptr.Ptr ty) where
@ -202,31 +151,32 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Shape_Tag) "unwrap")
instance HsBindgen.Runtime.HasCField.HasCField Shape_Tag "unwrap" where instance HsBindgen.Runtime.HasCField.HasCField Shape_Tag "unwrap" where
type CFieldType Shape_Tag "unwrap" = FC.CUInt type CFieldType Shape_Tag "unwrap" =
HsBindgen.Runtime.LibC.Word8
offset# = \_ -> \_ -> 0 offset# = \_ -> \_ -> 0
{-| __C declaration:__ @Circle@ {-| __C declaration:__ @Circle@
__defined at:__ @garnet_rs.h 12:3@ __defined at:__ @garnet_rs.h 12:9@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
pattern Circle :: Shape_Tag circle :: FC.CInt
pattern Circle = Shape_Tag 0 circle = (0 :: FC.CInt)
{-| __C declaration:__ @Rectangle@ {-| __C declaration:__ @Rectangle@
__defined at:__ @garnet_rs.h 13:3@ __defined at:__ @garnet_rs.h 13:9@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
pattern Rectangle :: Shape_Tag rectangle :: FC.CInt
pattern Rectangle = Shape_Tag 1 rectangle = (1 :: FC.CInt)
{-| __C declaration:__ @struct Circle_Body@ {-| __C declaration:__ @struct Circle_Body@
__defined at:__ @garnet_rs.h 16:8@ __defined at:__ @garnet_rs.h 15:16@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -234,7 +184,7 @@ data Circle_Body = Circle_Body
{ radius :: FC.CDouble { radius :: FC.CDouble
{- ^ __C declaration:__ @radius@ {- ^ __C declaration:__ @radius@
__defined at:__ @garnet_rs.h 17:10@ __defined at:__ @garnet_rs.h 16:10@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -280,7 +230,7 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Circle_Body) "radius
{-| __C declaration:__ @struct Rectangle_Body@ {-| __C declaration:__ @struct Rectangle_Body@
__defined at:__ @garnet_rs.h 20:8@ __defined at:__ @garnet_rs.h 19:16@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -288,14 +238,14 @@ data Rectangle_Body = Rectangle_Body
{ width :: FC.CDouble { width :: FC.CDouble
{- ^ __C declaration:__ @width@ {- ^ __C declaration:__ @width@
__defined at:__ @garnet_rs.h 21:10@ __defined at:__ @garnet_rs.h 20:10@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
, height :: FC.CDouble , height :: FC.CDouble
{- ^ __C declaration:__ @height@ {- ^ __C declaration:__ @height@
__defined at:__ @garnet_rs.h 22:10@ __defined at:__ @garnet_rs.h 21:10@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -355,7 +305,7 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Rectangle_Body) "hei
{-| __C declaration:__ @union \@Shape_body@ {-| __C declaration:__ @union \@Shape_body@
__defined at:__ @garnet_rs.h 27:3@ __defined at:__ @garnet_rs.h 26:3@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -378,7 +328,7 @@ deriving via HsBindgen.Runtime.Marshal.EquivStorable Shape_body instance F.Stora
__C declaration:__ @circle@ __C declaration:__ @circle@
__defined at:__ @garnet_rs.h 28:24@ __defined at:__ @garnet_rs.h 27:17@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -405,7 +355,7 @@ set_shape_body_circle =
__C declaration:__ @rectangle@ __C declaration:__ @rectangle@
__defined at:__ @garnet_rs.h 29:27@ __defined at:__ @garnet_rs.h 28:20@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -453,7 +403,7 @@ instance ( TyEq ty ((HsBindgen.Runtime.HasCField.CFieldType Shape_body) "rectang
{-| __C declaration:__ @struct Shape@ {-| __C declaration:__ @struct Shape@
__defined at:__ @garnet_rs.h 25:8@ __defined at:__ @garnet_rs.h 24:16@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -461,14 +411,14 @@ data Shape = Shape
{ tag :: Shape_Tag { tag :: Shape_Tag
{- ^ __C declaration:__ @tag@ {- ^ __C declaration:__ @tag@
__defined at:__ @garnet_rs.h 26:18@ __defined at:__ @garnet_rs.h 25:13@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
, body :: Shape_body , body :: Shape_body
{- ^ __C declaration:__ @body@ {- ^ __C declaration:__ @body@
__defined at:__ @garnet_rs.h 30:5@ __defined at:__ @garnet_rs.h 29:5@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}

View File

@ -10,7 +10,6 @@ import qualified GHC.IO.Unsafe
import qualified GHC.Ptr as Ptr import qualified GHC.Ptr as Ptr
import qualified HsBindgen.Runtime.Internal.CAPI import qualified HsBindgen.Runtime.Internal.CAPI
import qualified HsBindgen.Runtime.Internal.HasFFIType import qualified HsBindgen.Runtime.Internal.HasFFIType
import qualified HsBindgen.Runtime.LibC
import qualified HsBindgen.Runtime.PtrConst import qualified HsBindgen.Runtime.PtrConst
import Data.Void (Void) import Data.Void (Void)
import GarnetRs import GarnetRs
@ -42,15 +41,6 @@ $(HsBindgen.Runtime.Internal.CAPI.addCSource (HsBindgen.Runtime.Internal.CAPI.un
, "{" , "{"
, " return &hello_shape;" , " return &hello_shape;"
, "}" , "}"
, "/* com_garnet_GarnetRs_get_add */"
, "__attribute__ ((const))"
, "int64_t (*hs_bindgen_bbabdbe61cd1eeb2 (void)) ("
, " int64_t arg1,"
, " int64_t arg2"
, ")"
, "{"
, " return &add;"
, "}"
])) ]))
-- __unique:__ @com_garnet_GarnetRs_get_hello@ -- __unique:__ @com_garnet_GarnetRs_get_hello@
@ -65,7 +55,7 @@ hs_bindgen_faf62265b53521d3 =
{-# NOINLINE hello #-} {-# NOINLINE hello #-}
{-| __C declaration:__ @hello@ {-| __C declaration:__ @hello@
__defined at:__ @garnet_rs.h 33:6@ __defined at:__ @garnet_rs.h 32:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -85,7 +75,7 @@ hs_bindgen_0f8c37ef19b17a6d =
{-# NOINLINE hello_struct #-} {-# NOINLINE hello_struct #-}
{-| __C declaration:__ @hello_struct@ {-| __C declaration:__ @hello_struct@
__defined at:__ @garnet_rs.h 35:6@ __defined at:__ @garnet_rs.h 34:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -105,30 +95,10 @@ hs_bindgen_287ff3ac660f333b =
{-# NOINLINE hello_shape #-} {-# NOINLINE hello_shape #-}
{-| __C declaration:__ @hello_shape@ {-| __C declaration:__ @hello_shape@
__defined at:__ @garnet_rs.h 37:6@ __defined at:__ @garnet_rs.h 36:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
hello_shape :: Ptr.FunPtr (Shape -> IO ()) hello_shape :: Ptr.FunPtr (Shape -> IO ())
hello_shape = hello_shape =
GHC.IO.Unsafe.unsafePerformIO hs_bindgen_287ff3ac660f333b GHC.IO.Unsafe.unsafePerformIO hs_bindgen_287ff3ac660f333b
-- __unique:__ @com_garnet_GarnetRs_get_add@
foreign import ccall unsafe "hs_bindgen_bbabdbe61cd1eeb2" hs_bindgen_bbabdbe61cd1eeb2_base ::
IO (Ptr.FunPtr Void)
-- __unique:__ @com_garnet_GarnetRs_get_add@
hs_bindgen_bbabdbe61cd1eeb2 :: IO (Ptr.FunPtr (HsBindgen.Runtime.LibC.Int64 -> HsBindgen.Runtime.LibC.Int64 -> IO HsBindgen.Runtime.LibC.Int64))
hs_bindgen_bbabdbe61cd1eeb2 =
HsBindgen.Runtime.Internal.HasFFIType.fromFFIType hs_bindgen_bbabdbe61cd1eeb2_base
{-# NOINLINE add #-}
{-| __C declaration:__ @add@
__defined at:__ @garnet_rs.h 39:32@
__exported by:__ @garnet_rs.h@
-}
add :: Ptr.FunPtr (HsBindgen.Runtime.LibC.Int64 -> HsBindgen.Runtime.LibC.Int64 -> IO HsBindgen.Runtime.LibC.Int64)
add =
GHC.IO.Unsafe.unsafePerformIO hs_bindgen_bbabdbe61cd1eeb2

View File

@ -7,11 +7,9 @@ module GarnetRs.Safe where
import qualified Foreign as F import qualified Foreign as F
import qualified Foreign.C as FC import qualified Foreign.C as FC
import qualified GHC.Int
import qualified GHC.Ptr as Ptr import qualified GHC.Ptr as Ptr
import qualified HsBindgen.Runtime.Internal.CAPI import qualified HsBindgen.Runtime.Internal.CAPI
import qualified HsBindgen.Runtime.Internal.HasFFIType import qualified HsBindgen.Runtime.Internal.HasFFIType
import qualified HsBindgen.Runtime.LibC
import qualified HsBindgen.Runtime.PtrConst import qualified HsBindgen.Runtime.PtrConst
import Data.Void (Void) import Data.Void (Void)
import GarnetRs import GarnetRs
@ -37,13 +35,6 @@ $(HsBindgen.Runtime.Internal.CAPI.addCSource (HsBindgen.Runtime.Internal.CAPI.un
, "{" , "{"
, " hello_shape(*arg1);" , " hello_shape(*arg1);"
, "}" , "}"
, "int64_t hs_bindgen_1c0c71fa74c428a9 ("
, " int64_t arg1,"
, " int64_t arg2"
, ")"
, "{"
, " return add(arg1, arg2);"
, "}"
])) ]))
-- __unique:__ @com_garnet_GarnetRs_Safe_hello@ -- __unique:__ @com_garnet_GarnetRs_Safe_hello@
@ -60,7 +51,7 @@ hs_bindgen_433ea2a26af4e593 =
{-| __C declaration:__ @hello@ {-| __C declaration:__ @hello@
__defined at:__ @garnet_rs.h 33:6@ __defined at:__ @garnet_rs.h 32:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -84,7 +75,7 @@ hs_bindgen_51157946af5519c9 =
{-| __C declaration:__ @hello_struct@ {-| __C declaration:__ @hello_struct@
__defined at:__ @garnet_rs.h 35:6@ __defined at:__ @garnet_rs.h 34:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -110,7 +101,7 @@ hs_bindgen_7de06f1fd827ca60 =
{-| __C declaration:__ @hello_shape@ {-| __C declaration:__ @hello_shape@
__defined at:__ @garnet_rs.h 37:6@ __defined at:__ @garnet_rs.h 36:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -121,35 +112,3 @@ hello_shape ::
hello_shape = hello_shape =
\s0 -> \s0 ->
F.with s0 (\s1 -> hs_bindgen_7de06f1fd827ca60 s1) F.with s0 (\s1 -> hs_bindgen_7de06f1fd827ca60 s1)
-- __unique:__ @com_garnet_GarnetRs_Safe_add@
foreign import ccall safe "hs_bindgen_1c0c71fa74c428a9" hs_bindgen_1c0c71fa74c428a9_base ::
GHC.Int.Int64
-> GHC.Int.Int64
-> GHC.Int.Int64
-- __unique:__ @com_garnet_GarnetRs_Safe_add@
hs_bindgen_1c0c71fa74c428a9 ::
HsBindgen.Runtime.LibC.Int64
-> HsBindgen.Runtime.LibC.Int64
-> HsBindgen.Runtime.LibC.Int64
hs_bindgen_1c0c71fa74c428a9 =
HsBindgen.Runtime.Internal.HasFFIType.fromFFIType hs_bindgen_1c0c71fa74c428a9_base
{-|
Marked @__attribute((const))__@
__C declaration:__ @add@
__defined at:__ @garnet_rs.h 39:32@
__exported by:__ @garnet_rs.h@
-}
add ::
HsBindgen.Runtime.LibC.Int64
-- ^ __C declaration:__ @a@
-> HsBindgen.Runtime.LibC.Int64
-- ^ __C declaration:__ @b@
-> HsBindgen.Runtime.LibC.Int64
add = hs_bindgen_1c0c71fa74c428a9

View File

@ -7,11 +7,9 @@ module GarnetRs.Unsafe where
import qualified Foreign as F import qualified Foreign as F
import qualified Foreign.C as FC import qualified Foreign.C as FC
import qualified GHC.Int
import qualified GHC.Ptr as Ptr import qualified GHC.Ptr as Ptr
import qualified HsBindgen.Runtime.Internal.CAPI import qualified HsBindgen.Runtime.Internal.CAPI
import qualified HsBindgen.Runtime.Internal.HasFFIType import qualified HsBindgen.Runtime.Internal.HasFFIType
import qualified HsBindgen.Runtime.LibC
import qualified HsBindgen.Runtime.PtrConst import qualified HsBindgen.Runtime.PtrConst
import Data.Void (Void) import Data.Void (Void)
import GarnetRs import GarnetRs
@ -37,13 +35,6 @@ $(HsBindgen.Runtime.Internal.CAPI.addCSource (HsBindgen.Runtime.Internal.CAPI.un
, "{" , "{"
, " hello_shape(*arg1);" , " hello_shape(*arg1);"
, "}" , "}"
, "int64_t hs_bindgen_20eb651f0a8faf48 ("
, " int64_t arg1,"
, " int64_t arg2"
, ")"
, "{"
, " return add(arg1, arg2);"
, "}"
])) ]))
-- __unique:__ @com_garnet_GarnetRs_Unsafe_hello@ -- __unique:__ @com_garnet_GarnetRs_Unsafe_hello@
@ -60,7 +51,7 @@ hs_bindgen_2dfe97662a4d6377 =
{-| __C declaration:__ @hello@ {-| __C declaration:__ @hello@
__defined at:__ @garnet_rs.h 33:6@ __defined at:__ @garnet_rs.h 32:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -84,7 +75,7 @@ hs_bindgen_29d823ada2bc7302 =
{-| __C declaration:__ @hello_struct@ {-| __C declaration:__ @hello_struct@
__defined at:__ @garnet_rs.h 35:6@ __defined at:__ @garnet_rs.h 34:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -110,7 +101,7 @@ hs_bindgen_b3f40a03f07eaa85 =
{-| __C declaration:__ @hello_shape@ {-| __C declaration:__ @hello_shape@
__defined at:__ @garnet_rs.h 37:6@ __defined at:__ @garnet_rs.h 36:6@
__exported by:__ @garnet_rs.h@ __exported by:__ @garnet_rs.h@
-} -}
@ -121,35 +112,3 @@ hello_shape ::
hello_shape = hello_shape =
\s0 -> \s0 ->
F.with s0 (\s1 -> hs_bindgen_b3f40a03f07eaa85 s1) F.with s0 (\s1 -> hs_bindgen_b3f40a03f07eaa85 s1)
-- __unique:__ @com_garnet_GarnetRs_Unsafe_add@
foreign import ccall unsafe "hs_bindgen_20eb651f0a8faf48" hs_bindgen_20eb651f0a8faf48_base ::
GHC.Int.Int64
-> GHC.Int.Int64
-> GHC.Int.Int64
-- __unique:__ @com_garnet_GarnetRs_Unsafe_add@
hs_bindgen_20eb651f0a8faf48 ::
HsBindgen.Runtime.LibC.Int64
-> HsBindgen.Runtime.LibC.Int64
-> HsBindgen.Runtime.LibC.Int64
hs_bindgen_20eb651f0a8faf48 =
HsBindgen.Runtime.Internal.HasFFIType.fromFFIType hs_bindgen_20eb651f0a8faf48_base
{-|
Marked @__attribute((const))__@
__C declaration:__ @add@
__defined at:__ @garnet_rs.h 39:32@
__exported by:__ @garnet_rs.h@
-}
add ::
HsBindgen.Runtime.LibC.Int64
-- ^ __C declaration:__ @a@
-> HsBindgen.Runtime.LibC.Int64
-- ^ __C declaration:__ @b@
-> HsBindgen.Runtime.LibC.Int64
add = hs_bindgen_20eb651f0a8faf48

View File

@ -3,37 +3,34 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
struct T { typedef struct T {
bool a; bool a;
uint8_t b; uint8_t b;
}; } T;
enum Shape_Tag { typedef uint8_t Shape_Tag;
Circle, #define Circle 0
Rectangle, #define Rectangle 1
};
struct Circle_Body { typedef struct Circle_Body {
double radius; double radius;
}; } Circle_Body;
struct Rectangle_Body { typedef struct Rectangle_Body {
double width; double width;
double height; double height;
}; } Rectangle_Body;
struct Shape { typedef struct Shape {
enum Shape_Tag tag; Shape_Tag tag;
union { union {
struct Circle_Body circle; Circle_Body circle;
struct Rectangle_Body rectangle; Rectangle_Body rectangle;
} body; } body;
}; } Shape;
void hello(const char *c); void hello(const char *c);
void hello_struct(struct T t); void hello_struct(struct T t);
void hello_shape(struct Shape s); void hello_shape(struct Shape s);
__attribute__((const)) int64_t add(int64_t a, int64_t b);

View File

@ -22,7 +22,7 @@ extern "C" fn hello_struct(t: T) -> () {
say_hello(&format!("{:?}", t)) say_hello(&format!("{:?}", t))
} }
#[repr(C)] #[repr(C, u8)]
#[derive(Debug)] #[derive(Debug)]
enum Shape { enum Shape {
Circle { radius: f64 }, Circle { radius: f64 },
@ -33,9 +33,3 @@ enum Shape {
extern "C" fn hello_shape(s: Shape) -> () { extern "C" fn hello_shape(s: Shape) -> () {
say_hello(&format!("{:?}", s)) say_hello(&format!("{:?}", s))
} }
/// cbindgen:prefix=__attribute__((const))
#[unsafe(no_mangle)]
extern "C" fn add(a: i64, b: i64) -> i64 {
a + b
}