我想使用 Haskell 的 FFI 功能在 C 和 Haskell 之间共享数据(在最简单的情况下是整数数组)。C 端创建数据(相应地分配内存),但在它被释放之前永远不会修改它,所以我认为以下方法是“安全的”:
ForeignPtr,设置了一个调用释放指针的 C 函数的终结器。Vector使用可以(不可变地)在 Haskell 代码中使用的外部指针构建一个。但是,使用这种方法会导致相当不确定的崩溃。小例子倾向于工作,但“一旦在GC踢”,我开始得到分段错误的各种错误,以“BARF” S在此或此行GHC的GC的“疏散”的一部分。
我在这里做错了什么?做这样的事情的“正确方法”是什么?
我有一个带有以下声明的 C 头文件:
typedef struct CVector {
const int32_t *pointer;
size_t length;
} Vector;
void create_c_vector(struct CVector *vector);
void free_buffer(void *buff);
Run Code Online (Sandbox Code Playgroud)
Haskell 代码是.chs使用c2hs从以下文件生成的:
import Foreign.C.Types
import Foreign.Concurrent
import Foreign.Marshal.Alloc
import Foreign.Ptr
import Foreign.Storable
import qualified Data.Vector.Storable as V
#include <cvector.h>
data ForeignVector = ForeignVector …Run Code Online (Sandbox Code Playgroud) 我有一些特征(删除函数和一些参数膨胀后)看起来像:
trait Foo { }
trait Boo { }
trait Bar<T: Foo> { }
trait Baz { }
Run Code Online (Sandbox Code Playgroud)
如果U实现Bar<T>了一些T实现Foo 和 U实现Boo,那么就可以派生Bazfor 的实现U.但是,我无法编写有效的Rust代码.
几次尝试是:
impl<T: Foo, U: Bar<T> + Boo> Baz for U { }
Run Code Online (Sandbox Code Playgroud)
这使
错误:类型参数
T不受impl trait,self type或谓词约束[E0207]
而
impl<U: Bar<T> + Boo> Baz for U { }
Run Code Online (Sandbox Code Playgroud)
产量
错误:类型名称
T未定义或未在范围内[E0412]
一个/怎么可能在(稳定)Rust(希望没有任何动态调度)中做到这一点?
编辑:有些人暗示了一些类似的问题,基本上有两种方法(我发现它们都不适合我的情况):
T,例如我想写一些功能,这有这样一个签名fn bla<T: Foo, U: Bar<T>, V: …我正在编写一些代码来表达从给定类型的成员构建的"表达式":
data Expr a = Simply a | Add (Expr a, Expr a) | Mult (Expr a, Expr a)
Run Code Online (Sandbox Code Playgroud)
可以定义一些中缀运算符以使构造它们更方便:
(+++) :: Expr a -> Expr a -> Expr a
x +++ y = Add (x, y)
(***) :: Expr a -> Expr a -> Expr a
x *** y = Mult (x, y)
Run Code Online (Sandbox Code Playgroud)
因此,人们可以写
(Simply "bar") +++ ((Simply "fo") *** (Simply "o"))
Run Code Online (Sandbox Code Playgroud)
要得到
Add (Simply "bar",Mult (Simply "fo",Simply "o"))
Run Code Online (Sandbox Code Playgroud)
现在的问题是,是否有一种方法可以省略构造函数Simply,即a隐式地将该类型的任何成员视为成员,Expr a并直接从中获取上述示例("bar") +++ …