问题标签 [haskell-ffi]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
82 浏览

haskell - Haskell FFI - 返回更新的结构

我有以下C要调用的函数Haskell

该函数应该接收一些property_list_t并在其中填充一些值,因此调用者具有更新的结构。

我有所有必要的包装器property_list_t(比如Storable等),但我不知道如何把这个函数包装成类似的东西

我尝试使用C2HS,还尝试手动编写 FFI 绑定,例如:

但在这两种情况下,我都得到了我原来的“人口不足”名单。

如何将更新的结构返回给 Haskell?

0 投票
0 回答
162 浏览

c++ - 如何使用 Haskell FFI 生成静态库?

今天为了编译一个在 C++ 中使用的 haskell 库,我使用堆栈 ghc:

它可以工作,但是部署有问题,当我在生成的库上使用 ldd 命令时,所有路径都指向我的 HOME 文件夹,我想生成一个具有静态依赖项的静态库,以避免在用户上安装 Haskell系统。

Ps:我将在 C++ 代码上使用 Haskell 库,但 Haskell FFI 仅适用于 C。

0 投票
1 回答
359 浏览

haskell - 如何从 Haskell 链接到 C#(即托管)DLL?

我正在尝试从我的 Haskell 代码构建一个 Windows DLL。应该从 C# 中的托管代码调用此 DLL 中的函数。并且,至少有一个函数(在 c# 代码中定义)将从此 DLL 中的函数调用。

冒着过度解释的风险,这里有一个小图来描述我想要的:

我设法使(1)完美地工作,即DLL中的Haskell函数由C#代码调用,结构和数组的编组正确,Haskell中函数执行的结果也是正确的。到现在为止还挺好。

问题在于(2),即来自 Haskell(在 DLL 中)的函数调用 C# 中定义的托管函数。问题出在构建本身 - 我还没有真正检查 (2) 的结果。

由于 c# 托管代码中的 fn_call_from_hs() 是在 C# 中定义的,因此我在 Haskell 代码(在 DLL 中)中只有“导入”的函数符号:

现在,当我使用堆栈构建我的 Haskell 项目时,它构建 Haskell DLL 没有问题,但构建继续也链接“main.exe” - 这失败(显然),因为在任何地方都没有定义函数 fn_call_from_hs() Haskell 代码(在 c# 中定义)。

在构建 HsDLL.dll 后,有什么方法可以阻止堆栈继续构建 main.exe?我对具有未解析符号 (fn_call_from_hs()) 的 HsDLL.dll 没问题,因为在托管 C# 代码加载此 DLL 期间,运行时链接器将找到此符号。

到目前为止,我已经尝试了这些步骤,但没有一个有帮助:

  1. 从 package.yaml 中删除了“可执行文件”和“测试”
  2. 添加了 GHC 选项:-no-hs-main在 package.yaml 中。包含 HsDLL 构建的 package.yaml 部分如下所示:

    1. 完全删除了 Main 模块(即,从“app”文件夹中删除了由堆栈自动创建的 Main.hs)
    2. -dynamic在 ghc-options 中添加了该标志,希望 GHC 会假设未解析的符号将在其他地方定义,但这带来了其他问题:GHC 现在抱怨它需要“dyn”base 库等。

所以,最后,我总是这样结束:

所以,我的问题是:(1)我完全不知道如何停止链接“main.exe”!我知道函数 fn_call_from_hs() 没有在 HsDLL 中定义,但是,正如我所说,我没问题,因为它是在托管 c# 代码中定义的。我只想不构建 main.exe。

或者

(2) 我是否应该继续-dynamic向 GHC 添加标志(保持所有其他标志如上所述)?在这种情况下,我如何获得堆栈来安装 GHC 抱怨的“dyn”库?

有人可以帮助我吗?提前感谢您耐心阅读这个(相当长的)问题!

0 投票
1 回答
138 浏览

c - Haskell FFI:包装包含单独分配的字符串(char *)的C结构

假设你有一个 C-struct

以及对其进行一些操作的函数f

C API 要求char*在调用之前分配足够的缓冲区f

(请注意,该num字段在此构造示例中没有任何用途。它只是防止使用CStringand的简单解决方案CStringLen。)

问题是如何为这种 C API 编写 Haskell FFI。

我想出的是:从

并编写一个可存储的实例。我的想法是在最后分配 64 个字节作为字符串的缓冲区:

poke必须更改 str 中的指针以指向分配的缓冲区,然后必须将 Haskell 字符串复制到其中。我这样做withCStringLen

最后是peek,这很简单:

所有这些都有效,但我觉得它相当难看。这是这样做的方法,还是有更好的方法?

如果有人想玩它,小玩具问题在github 上

更新

chi正如以下警告所指出的那样:使用硬编码的对齐和偏移是不好的做法。它们很脆弱并且依赖于平台/编译器。相反,应该使用c2hscc2hsbindings-dslgreencard等工具。

0 投票
1 回答
78 浏览

haskell - 堆栈构建找不到本地库

我自己使用 GHC 成功地复制了这个例子。

最终目标是用 Haskell 编写 99% 的程序,然后从用 C 编写的事件循环中调用它:

在 C 中运行事件循环的动机是,据我所知,在 Haskell 中强制评估 X 次/秒是困难的或不可能的。

这是 package.yaml:

当我运行时:

我明白了:

有谁知道发生了什么?

0 投票
1 回答
98 浏览

haskell - 如何从 Haskell 调用 C++ Setter 和 Getter

我知道如何从 Haskell 调用纯 C++ 函数,但想知道如何让 GHC 接受有副作用的函数。

我希望 Haskell 具有对 C++ 链表的只读访问权限,以及对 C++ 变量的独占写入访问权限。例如:

尽管 getVal() 没有副作用,但它是一个明显有副作用的类的一部分,所以我不清楚是否需要偷偷摸摸的技巧才能让 GHC 接受它。

setVal(int) 明显有副作用,那怎么让 GHC 不在乎呢?

0 投票
1 回答
77 浏览

haskell - 如何使用 Haskell 的 FunPtr?

假设以下文件:

测试2.h:

测试2.c:

测试2.hs:

使用以下编译:

(GHC 在lol2 声明之前发出关于缺少“&”的警告,但我认为警告是错误的,所以我忽略它。另外,请注意我没有使用-dynamic。如果我这样做,结果是一样的)

但是,我在运行时得到一个 SIGSEGV:

崩溃后,堆栈似乎无法使用:

我究竟做错了什么?我该如何调试呢?

0 投票
1 回答
123 浏览

haskell - 将 Data.ByteString.Lazy 转换为 CStringLen 的最有效方法

我需要将一些数据编码为 JSON,然后使用 hsyslog 推送到 syslog。两个相关函数的类型是:

转换 a 的最有效方法(速度和内存)是Lazy.ByteString -> CStringLen什么?我找到Data.ByteString.Unsafe了,但它只适用于ByteString,而不是Lazy.ByteString

我应该坚持一个unsafeUseAsCStringLen . Data.String.Conv.toS并收工吗?它会以正确的方式提高效率吗?

0 投票
1 回答
54 浏览

haskell - UB是否由于allocaArray自动清理?

我的代码中有这个功能似乎工作得很好:

(对于上下文,这是从 Vulkan API 获取 FFI 数组的辅助函数,例如 f 可能是vkEnumeratePhysicalDevices

当我查看我的代码时,我注意到它返回 resArray(从 allocaArray 的描述中似乎只在内部 lambda 中有效)给它的调用者。在 C 中,这样的代码将是未定义的行为。我的直觉在这里是正确的还是有更多的事情发生?毕竟我还没有注意到任何崩溃:)

0 投票
0 回答
81 浏览

c - Haskell 函数接受并返回一个“c”数组

我正在寻找概念上具有签名的 Haskell FFI 函数的完整工作示例:ByteString -> ByteString,即:

  1. 将一个 8 位无符号整数数组作为输入,该数组已分配在“c”堆上(即生命周期超过 FFI 调用)。
  2. 将数组转换为 a ByteString(假设ByteString不能直接在 FFI API 中使用)。
  3. 以某种方式不变地转换ByteString(简单的例子:反转它)。
  4. 将转换后的(或所需的任何 FFI 表示)返回到调用“c”函数ByteString,以便必须在“c”端删除它。

谷歌搜索显示了各种相关和/或部分信息,但这里的细节非常重要:我无法在任何地方找到相关的 MWE(人们认为是基本的 FFI 应用程序)。

编辑:一位评论者亲切地指出 ByteString 已经封装了一个指针和一个长度。

这导致了一些更具体的问题:

Q1。对应的“c”函数签名 ByteString -> ByteString应该是什么?

例如,是否有必要在“c”端显式定义 ByteString?

看起来直接翻译它不会产生有效的 FFI 调用。为了:

编译器错误是“无法在外部调用中编组字节字符串”。

Q2 arg 是否必须在 Haskell 端以某种方式转换为 ByteString 或者它(打算)在结构上同构的事实是否足够?