【发布时间】:2016-01-28 00:28:54
【问题描述】:
我正在尝试使用 Haskell 和 Repa/DevIL 对图形文件执行一系列转换。使用的起始示例由 Haskell wiki 页面 https://wiki.haskell.org/Numeric_Haskell:_A_Repa_Tutorial 提供。我是一名命令式程序员,拥有 30 年的一些 erlang 经验,并尝试在课堂环境之外学习 Haskell。
问题是在文件加载首先转换为 Repa 数组后操作数据:
import Data.Array.Repa.IO.DevIL (runIL,readImage,writeImage,Image(RGB),IL)
import qualified Data.Array.Repa as R
import Data.Vector.Unboxed as DVU
import Control.Monad
main :: IO ()
main = do
[f] <- getArgs
(RGB a) <- runIL $ Data.Array.Repa.IO.DevIL.readImage f
let
c = (computeP (R.traverse a id rgbTransform)) :: IL (Array U DIM3 Float)
已成功转换为类型“Array F DIM3 Float”作为 rgbTransform 的输出。从那时起,使用数据就成了一场噩梦。在 F(oreign) 和 U(nboxed) 之间切换数组存储类型会改变所有后续调用的可用性,加上 Repa 添加的 monad 层 IL 强制在第一次变换之后的几乎每个方程中使用 liftM:
let -- continued
sh = liftM R.extent c -- IL DIM3
v = liftM R.toUnboxed c -- IL (Vector Float)
lv = liftM DVU.length v -- IL Int
f = liftM indexed v -- vector of tuples: (Int,a) where Int is idx
k = (Z :. 2) :. 2 :. 0 :: DIM3
这些是我可以毫无错误地调用的例程。由于 IL monad 层,IO monad 的 print 命令如果放置在这个 'let' 列表中或之后不会产生任何输出。
好奇者的游戏计划:
- 读取图形文件(通过 Repa 完成)
- 调整图像大小(未完成,Repa 中没有调整大小,必须手动编码)
- 将图像从 Word8 转换并转换为 Float(完成)
- 获取一个指向转换后的浮点数据的稳定指针(未完成)
- 将浮点数据就地转换为 C 结构数组 {Float a,b,c;},由外部 C 例程通过 FFI(不完全 完毕)。希望这是在不编组新图形的情况下完成的 数组通过传递指向数据的指针
- 对转换后的数据执行更多次传递以提取更多信息(部分完成)。
我正在寻求有关问题 4 和 5 的帮助。
4 -> 在尝试获取 C 可用内存指针时,类型系统一直难以处理。遍历大量的 haskell 库调用并没有帮助。
5 -> 外部 C 例程的类型为:
foreign import ccall unsafe "transform.h xform"
c_xform :: Ptr (CFloat,CFloat,CFloat) ->
CInt ->
IO ()
Ptr 应该指向一个未装箱的平面 C 数组 rgb_t 结构:
typedef struct
{
float r;
float g;
float b;
} rgb_t;
关于如何在 FFI 中处理数组指针的可用基于 Web 的 FFI 描述即使不是完全晦涩难懂的,也是不存在的。解冻并传入浮点 RGB 结构的 C 数组,就地修改它们然后冻结结果的相当简单的想法是我的想法。外部转换是纯粹的,因为相同的输入将产生可预测的输出,不使用线程,不使用全局变量,也不依赖于晦涩的库。
【问题讨论】:
-
Err...
Ptr (CFloat, CFloat, CFloat)类型的值绝不保证指向可以有意义地被视为具有三个floats 的 C 结构的内存位置。我希望你'在你的游戏计划中不依赖它......(AFAIK 在 FFI 规范中完全没有关于处理 C 结构的规定。)
标签: c arrays haskell struct ffi