Compare commits
9 Commits
352bf8c286
...
0c70b2a3f7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c70b2a3f7 | ||
|
|
c735ffb4f3 | ||
|
|
8847012bbc | ||
|
|
9417c06574 | ||
|
|
32de67723b | ||
|
|
c32606904f | ||
|
|
82c9262e91 | ||
|
|
aaaf02b783 | ||
|
|
621a44caa9 |
@ -9,8 +9,6 @@ main = do
|
||||
hello "Haskell"
|
||||
helloStruct T{a = True, b = 42}
|
||||
helloStruct T{a = False, b = maxBound}
|
||||
helloEnum E1
|
||||
helloEnum E3
|
||||
helloShape $ Circle 3.14
|
||||
helloShape $ Rectangle 10.0 5.0
|
||||
putStrLn $ "3 + 4 = " <> show (add 3 4)
|
||||
|
||||
13
flake.lock
generated
13
flake.lock
generated
@ -527,16 +527,15 @@
|
||||
"hs-bindgen-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1774599157,
|
||||
"narHash": "sha256-jgV67xhWzxMwyiyy5RPtu+VQvGTt+FoMXCWJcZ7lczY=",
|
||||
"lastModified": 1774379170,
|
||||
"narHash": "sha256-lZV6IdCBf8uCt21qB5mfgLaP9CNgho/HsqjvkulDR2Q=",
|
||||
"owner": "well-typed",
|
||||
"repo": "hs-bindgen",
|
||||
"rev": "3c4af10590d0d09e825a9735e9a03d7f60914e21",
|
||||
"rev": "4b6febb5cc6196835bd2890a3ab27a88dab1806b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "well-typed",
|
||||
"ref": "release-0.1-alpha2",
|
||||
"repo": "hs-bindgen",
|
||||
"type": "github"
|
||||
}
|
||||
@ -561,11 +560,11 @@
|
||||
"libclang-src": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1774600891,
|
||||
"narHash": "sha256-LTAyNMY4Vu0vPeEq2wXB0KWY4kGtqtHTRmADjLdkv78=",
|
||||
"lastModified": 1774018529,
|
||||
"narHash": "sha256-Bo5wvityXKCmlnrobtI9WkA1maR7sfkDXo1VOZvrPLk=",
|
||||
"owner": "well-typed",
|
||||
"repo": "libclang",
|
||||
"rev": "1054474fae403bfb52c7919680cac03d3d3d4237",
|
||||
"rev": "83387d72a8dfae9f75d27db6b32ea37afab06268",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
nix-haskell.url = "github:reflex-frp/nix-haskell";
|
||||
nixpkgs.follows = "nix-haskell/nixpkgs";
|
||||
hls-src = { url = "github:haskell/haskell-language-server/2.13.0.0"; flake = false; };
|
||||
hs-bindgen-src = { url = "github:well-typed/hs-bindgen/release-0.1-alpha2"; flake = false; };
|
||||
hs-bindgen-src = { url = "github:well-typed/hs-bindgen"; flake = false; };
|
||||
libclang-src = { url = "github:well-typed/libclang"; flake = false; };
|
||||
flake-utils.url = "github:numtide/flake-utils";
|
||||
crane.url = "github:ipetkov/crane";
|
||||
|
||||
11
garnet.cabal
11
garnet.cabal
@ -6,13 +6,6 @@ author: Patrick Aldis
|
||||
maintainer:
|
||||
george.thomas@obsidian.systems
|
||||
patrick.aldis@obsidian.systems
|
||||
-- aha, nice, this does fix recompilation checking
|
||||
extra-source-files:
|
||||
rust/target/debug/garnet_rs.h
|
||||
-- that could be problematic given file is gitignored? unfortunately this doesn't work
|
||||
-- tbf, I haven't even looked up the docs, just saw the autocompletion
|
||||
-- extra-tmp-files:
|
||||
-- rust/target/debug/garnet_rs.h
|
||||
|
||||
common common
|
||||
default-language: GHC2024
|
||||
@ -50,13 +43,11 @@ library
|
||||
GarnetRs.Wrapped
|
||||
hs-source-dirs: lib
|
||||
include-dirs: rust/target/debug
|
||||
-- HLS gives up entirely when the header is malformed if we do this
|
||||
-- and anyway, I don't think it gives us dependency tracking like `extra-source-files` does
|
||||
-- includes: garnet_rs.h
|
||||
extra-bundled-libraries: Cgarnet_rs
|
||||
build-depends:
|
||||
hs-bindgen,
|
||||
hs-bindgen-runtime,
|
||||
primitive,
|
||||
template-haskell,
|
||||
|
||||
executable garnet
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{-# LANGUAGE CApiFFI #-}
|
||||
{-# LANGUAGE DerivingVia #-}
|
||||
{-# LANGUAGE FieldSelectors #-}
|
||||
{-# LANGUAGE MagicHash #-}
|
||||
{-# LANGUAGE PatternSynonyms #-}
|
||||
{-# LANGUAGE TemplateHaskell #-}
|
||||
@ -29,15 +30,7 @@ import HsBindgen.TH
|
||||
import Language.Haskell.TH
|
||||
import System.Process
|
||||
|
||||
import Control.Monad.IO.Class (MonadIO (liftIO))
|
||||
import Language.Haskell.TH.Syntax (addDependentFile)
|
||||
import System.Directory.Extra (getCurrentDirectory)
|
||||
|
||||
do
|
||||
-- not sure this does anything - hs-bindgen should already be doing the tracking, and the issues are from elsewhere
|
||||
-- dir <- liftIO getCurrentDirectory
|
||||
-- liftIO $ print dir
|
||||
-- addDependentFile $ dir <> "/rust/target/debug/garnet_rs.h"
|
||||
systemDirs <- -- TODO bit of a hack
|
||||
map (Dir . T.unpack . T.strip)
|
||||
. concatMap (takeWhile (maybe False ((== ' ') . fst) . T.uncons) . dropWhile T.null . T.lines)
|
||||
|
||||
@ -1,20 +1,11 @@
|
||||
{-# LANGUAGE PatternSynonyms #-}
|
||||
|
||||
-- TODO automate this sort of high level wrapper boilerplate
|
||||
-- or look at upstream plans: https://github.com/well-typed/hs-bindgen/issues?q=state%3Aopen%20label%3A%22highlevel%22
|
||||
module GarnetRs.Wrapped (
|
||||
T (..),
|
||||
Raw.E (..),
|
||||
-- TODO hmm, we don't really want to have to list all of these...
|
||||
-- is there an option to make them not be patterns at all?
|
||||
pattern Raw.E1,
|
||||
pattern Raw.E2,
|
||||
pattern Raw.E3,
|
||||
Shape (..),
|
||||
BTree (..),
|
||||
hello,
|
||||
helloStruct,
|
||||
helloEnum,
|
||||
helloShape,
|
||||
add,
|
||||
sumTree,
|
||||
@ -47,6 +38,7 @@ data Shape
|
||||
convertShape :: Shape -> Raw.Shape
|
||||
convertShape = \case
|
||||
Circle r -> Raw.Shape Raw.Circle $ Raw.set_shape_circle_circle $ Raw.Circle_Body r
|
||||
-- hmm, unintuitive name
|
||||
Rectangle w h -> Raw.Shape Raw.Rectangle $ Raw.set_shape_circle_rectangle $ Raw.Rectangle_Body w h
|
||||
|
||||
data BTree a
|
||||
@ -71,9 +63,6 @@ hello = flip useAsCString $ Raw.hello . unsafeFromPtr
|
||||
helloStruct :: T -> IO ()
|
||||
helloStruct = flip with (Raw.hello_struct . unsafeFromPtr) . convertT
|
||||
|
||||
helloEnum :: Raw.E -> IO ()
|
||||
helloEnum = flip with (Raw.hello_enum . unsafeFromPtr)
|
||||
|
||||
helloShape :: Shape -> IO ()
|
||||
helloShape = flip with (Raw.hello_shape . unsafeFromPtr) . convertShape
|
||||
|
||||
|
||||
@ -2,22 +2,6 @@ use std::env;
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
// this doesn't make _much_ difference really, since this is our only Rust source file
|
||||
// but it seems it's probably better than not having it
|
||||
// what we really want is to tell Rust to only regenerate the header file if the Rust code actually compiles
|
||||
// but we don't have that flexibility
|
||||
// and it's an issue because cbindgen tries to be fault-tolerant in some ways that don't even seem to make sense
|
||||
//
|
||||
// e.g. mis-spell "Option" as "Option" and you get
|
||||
// void print_optional(Optio<const int8_t*> x);
|
||||
// instead of
|
||||
// void print_optional(const int8_t *x);
|
||||
// and that's only an issue because in HLS TH dependent-file watching gives up after an error
|
||||
// i.e. once the containing splice has thrown an exception once, the containing file needs a manual edit to kick it
|
||||
// P.S. strings to stdout?! what a terrible API
|
||||
// don't get me started in the discoverability of actually then using the terminal for debugging:
|
||||
// println!("cargo::warning={:?}", env::var("OUT_DIR"));
|
||||
println!("cargo::rerun-if-changed=lib.rs");
|
||||
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
|
||||
let profile = env::var("PROFILE").unwrap();
|
||||
cbindgen::Builder::new()
|
||||
|
||||
28
rust/lib.rs
28
rust/lib.rs
@ -11,7 +11,7 @@ fn say_hello(name: &str) {
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn hello(c: *const c_char) {
|
||||
extern "C" fn hello(c: *const c_char) -> () {
|
||||
say_hello(unsafe { CStr::from_ptr(c) }.to_str().unwrap())
|
||||
}
|
||||
|
||||
@ -23,23 +23,10 @@ struct T {
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn hello_struct(t: &T) {
|
||||
extern "C" fn hello_struct(t: &T) -> () {
|
||||
say_hello(&format!("{:?}", t))
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
enum E {
|
||||
E1,
|
||||
E2,
|
||||
E3,
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn hello_enum(e: &E) {
|
||||
say_hello(&format!("{:?}", e))
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
enum Shape {
|
||||
@ -48,7 +35,7 @@ enum Shape {
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn hello_shape(s: &Shape) {
|
||||
extern "C" fn hello_shape(s: &Shape) -> () {
|
||||
say_hello(&format!("{:?}", s))
|
||||
}
|
||||
|
||||
@ -93,7 +80,7 @@ enum BTreeC {
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn sum_tree(t: &BTreeC) -> i64 {
|
||||
(unsafe { std::mem::transmute::<&BTreeC, &BTree<i64>>(t) }).sum()
|
||||
(unsafe { std::mem::transmute::<_, &BTree<i64>>(t) }).sum()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@ -102,8 +89,9 @@ extern "C" fn sum_slice(v: *const i64, s: usize) -> i64 {
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
extern "C" fn print_optional(x: Option<&i8>) {
|
||||
if let Some(x) = x {
|
||||
println!("{}", x / 2)
|
||||
extern "C" fn print_optional(x: Option<&i8>) -> () {
|
||||
match x {
|
||||
Some(x) => println!("{}", x / 2),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user