如何在没有c2hs或其他工具的情况下为此结构创建可存储的实例? [英] How do I create a storable instance for this structure without c2hs or other tools?

查看:95
本文介绍了如何在没有c2hs或其他工具的情况下为此结构创建可存储的实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


$ b

  typedef struct Atom_ {
float x;
float y;
float z;
int col;
} Atom;

对应于此类型:

  data Atom = Atom {pos :: V3 Float,col :: Int} 

如何为 Atom 创建一个可存储的实例,以便我可以将Haskell上的 Atom s发送给C函数,期望一个 Atom

解决方案

保证这将完全按照所显示的工作(我没有在这台计算机上设置环境),但它应该是朝着正确的方向迈出的第一步:

  import Foreign.Storable 
import Foreign.Ptr

instance可存储的Atom,其中
- 不让这个静态的,让编译器选择取决于
- 在平台上
sizeOf _ = 3 * sizeOf(0 :: Float)+ sizeOf(0 :: Int)
- 您可能需要摆弄这个,如果你有这个能力,还有你的相应的C
- code对齐可能会非常棘手,但
- 在这种情况下,您可以非常安全地假定它将是
- 对于'Float`
alignment _ = alignment(0 ::浮动)
- 这些非常简单明了,显然订单在这里
- 很重要。我清楚地没有把它做成最优化它
- 可能是,我要清晰的代码而不是
peek ptr = do
let floatSize = sizeOf(0 :: Float )
x < - peek $ ptr`plusPtr`(0 * floatSize)
y < - peek $ ptr`plusPtr`(1 * floatSize)
z< - peek $ ptr`plusPtr` (2 * floatSize)
col < - peek $ ptr`plusPtr`(3 * floatSize)
return $ Atom(V3 xyz)col
poke ptr(Atom(V3 xyz)col) = do
let floatSize = sizeOf(0 :: Float)
poke(ptr`plusPtr`(0 * floatSize))x
poke(ptr`plusPtr`(1 * floatSize))y
poke(ptr`plusPtr`(2 * floatSize))z
poke(ptr`plusPtr`(3 * floatSize))col

这应该是正常的!它可能高度依赖于你的C编译器和你的平台,不过,你需要做一些广泛的测试,以确保它已经正确布置。


This structure:

typedef struct Atom_ {
    float x;
    float y;
    float z;
    int col;
} Atom;

corresponds to this type:

data Atom = Atom { pos :: V3 Float, col :: Int }

How do I create a storable instance for Atom so that I can send an Atoms on Haskell to a C function that expects an Atom?

解决方案

I can't currently guarantee that this will work exactly as shown (I don't have the environment set up on this computer), but it should be a good first step towards getting it right:

import Foreign.Storable
import Foreign.Ptr

instance Storable Atom where
    -- Don't make this static, let the compiler choose depending
    -- on the platform
    sizeOf _ = 3 * sizeOf (0 :: Float) + sizeOf (0 :: Int)
    -- You may need to fiddle with this, and with your corresponding C
    -- code if you have the ability to, alignment can be tricky, but
    -- in this case you can pretty safely assume it'll be the alignment
    -- for `Float`
    alignment _ = alignment (0 :: Float)
    -- These are pretty straightforward, and obviously order matters here
    -- a great deal.  I clearly haven't made this the most optimized it
    -- could be, I'm going for clarity of code instead
    peek ptr = do
        let floatSize = sizeOf (0 :: Float)
        x   <- peek $ ptr `plusPtr` (0 * floatSize)
        y   <- peek $ ptr `plusPtr` (1 * floatSize)
        z   <- peek $ ptr `plusPtr` (2 * floatSize)
        col <- peek $ ptr `plusPtr` (3 * floatSize)
        return $ Atom (V3 x y z) col
    poke ptr (Atom (V3 x y z) col) = do
        let floatSize = sizeOf (0 :: Float)
        poke (ptr `plusPtr` (0 * floatSize)) x
        poke (ptr `plusPtr` (1 * floatSize)) y
        poke (ptr `plusPtr` (2 * floatSize)) z
        poke (ptr `plusPtr` (3 * floatSize)) col

And this should just work! It could be highly dependent on your C compiler and your platform, though, you'll want to do some extensive testing to make sure it's been laid out correctly.

这篇关于如何在没有c2hs或其他工具的情况下为此结构创建可存储的实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆