如何 return 从 C/C++ 到 Idris 的数组?
How to return an array from C/C++ to Idris?
我想要 return 从 C/C++ 到 Idris 的任意等级的数组。我将 C++ 数组键入 void*
,相应地在 Idris 中有一个 AnyPtr
。在 Idris 中,我将 Array
类型定义为嵌套 Vect
:
Shape : {0 rank: Nat} -> Type
Shape = Vect rank Nat
Array : (0 shape : Shape) -> Type
Array [] = Int
Array (d :: ds) = Vect d (Array ds)
但我不知道如何将 AnyPtr
转换为 Array
。我已经达到
%foreign "C:libfoo,eval"
prim__eval : AnyPtr
export
eval : Array shape
eval = prim__eval -- doesn't type check
编辑 我将元素类型固定为 Int
因为它简化了问题而不会丢失重要的细节。
注:假设数组形状在 Idris 中是可访问的。
到得到一个数组
我们可以 return 一个 AnyPtr
指向数组的开头,然后编写一个函数在数组上递归获取每个点的元素。
例如(警告 - 未经过充分测试),
-- we index with Int not Nat because we can't use Nat in FFI
%foreign "C:libfoo,index_int32"
indexInt : AnyPtr -> Int -> Int
%foreign "C:libfoo,index_void_ptr")
indexArray : AnyPtr -> Int -> AnyPtr
%foreign "C:libfoo,get_array"
getArray : AnyPtr
%foreign "C:libfoo,get_int32"
getInt : Int
rangeTo : (n : Nat) -> Vect n Nat
rangeTo Z = []
rangeTo (S n) = snoc (rangeTo n) (S n)
build_array : (shape : Shape {rank=S _}) -> AnyPtr -> Array shape
build_array [n] ptr = map (indexInt ptr . cast . pred) (rangeTo n)
build_array (n :: r :: est) ptr =
map ((build_array (r :: est)) . (indexArray ptr . cast . pred)) (rangeTo n)
eval : {shape : _} -> Array shape
eval {shape=[]} = getInt
eval {shape=n :: rest} = map (build_array (n :: rest)) getArray
和
extern "C" { // if we're in C++
int32 index_i32(void* ptr, int32 idx) {
return ((int32*) ptr)[idx];
}
void* index_void_ptr(void** ptr, int32 idx) {
return ptr[idx];
}
int32 get_int32()
void* get_array()
}
向传递一个数组
你可以在C/C++中创建一个合适大小的数组,return一个指向那个数组的指针,然后和上面一样,递归地把Idris数组的每个元素赋值给C/C++ 数组。
我想要 return 从 C/C++ 到 Idris 的任意等级的数组。我将 C++ 数组键入 void*
,相应地在 Idris 中有一个 AnyPtr
。在 Idris 中,我将 Array
类型定义为嵌套 Vect
:
Shape : {0 rank: Nat} -> Type
Shape = Vect rank Nat
Array : (0 shape : Shape) -> Type
Array [] = Int
Array (d :: ds) = Vect d (Array ds)
但我不知道如何将 AnyPtr
转换为 Array
。我已经达到
%foreign "C:libfoo,eval"
prim__eval : AnyPtr
export
eval : Array shape
eval = prim__eval -- doesn't type check
编辑 我将元素类型固定为 Int
因为它简化了问题而不会丢失重要的细节。
注:假设数组形状在 Idris 中是可访问的。
到得到一个数组
我们可以 return 一个 AnyPtr
指向数组的开头,然后编写一个函数在数组上递归获取每个点的元素。
例如(警告 - 未经过充分测试),
-- we index with Int not Nat because we can't use Nat in FFI
%foreign "C:libfoo,index_int32"
indexInt : AnyPtr -> Int -> Int
%foreign "C:libfoo,index_void_ptr")
indexArray : AnyPtr -> Int -> AnyPtr
%foreign "C:libfoo,get_array"
getArray : AnyPtr
%foreign "C:libfoo,get_int32"
getInt : Int
rangeTo : (n : Nat) -> Vect n Nat
rangeTo Z = []
rangeTo (S n) = snoc (rangeTo n) (S n)
build_array : (shape : Shape {rank=S _}) -> AnyPtr -> Array shape
build_array [n] ptr = map (indexInt ptr . cast . pred) (rangeTo n)
build_array (n :: r :: est) ptr =
map ((build_array (r :: est)) . (indexArray ptr . cast . pred)) (rangeTo n)
eval : {shape : _} -> Array shape
eval {shape=[]} = getInt
eval {shape=n :: rest} = map (build_array (n :: rest)) getArray
和
extern "C" { // if we're in C++
int32 index_i32(void* ptr, int32 idx) {
return ((int32*) ptr)[idx];
}
void* index_void_ptr(void** ptr, int32 idx) {
return ptr[idx];
}
int32 get_int32()
void* get_array()
}
向传递一个数组
你可以在C/C++中创建一个合适大小的数组,return一个指向那个数组的指针,然后和上面一样,递归地把Idris数组的每个元素赋值给C/C++ 数组。