- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个关于 Haskell C FFI 的问题,特别是关于访问 C 库导出的静态数据结构。
我包装的 C 库具有静态数据结构,如 FOO_GEORGE
下面,以下列方式导出:
static struct foo_struct foo_table[] = { /* list of foo structs */ }
typedef struct foo_struct *foo_t;
foo_t FOO_GEORGE = &foo_table[0];
foo_t FOO_HARRY = &foo_table[1];
foo_t FOO_SUSAN = &foo_table[2];
/* ... */
我在 Haskell 库中需要的值是 foo_struct
的地址(&foo_table[n]
),即FOO_GEORGE
的内容,它以通常的方式放在一个不透明的新类型包装器中(构造函数不从库中导出,只导出类型):
newtype Foo = Foo { getFoo :: (Ptr Foo) }
这就是我现在正在做的:
foreign import ccall "&FOO_GEORGE" fooGeorgeHandle :: Ptr (Ptr Foo)
FooGeorge = Foo . unsafeDupablePerformIO . peek $ fooGeorgeHandle
我认为这是对 unsafePerformIO
的恰当使用, 因为 C API 和实现说 peek
的使用纯净无副作用。此外,我认为我不需要采取 documentation 中要点中列出的任何预防措施。 (以 {-# NOINLINE foo #-}
开头)。
我的总体问题是:我这样做对吗?以上分析是否正确?有没有更好或更好的方法来做到这一点?如果foreign import
子句允许我执行指针延迟,这很好,但似乎没有;我错过了什么吗?有人可能会争辩说,这将是一个不好的特性,因为如果指针不好,它可能会出现段错误——但是,peek
也是如此。我必须改用,所以结果是一样的。
谢谢!
最佳答案
John L. 建议使用 CApiFFI
扩展,它完全符合我的要求:允许您导入值而不是位置。现在:
{-# LANGUAGE CApiFFI #-}
newtype {-# CTYPE "foo.h" "struct foo_struct" #-} Foo = Foo { getFoo :: (Ptr Foo) }
foreign import capi "foo.h value FOO_GEORGE" fooGeorgePtr :: Ptr a
fooGeorge = Foo fooGeorgePtr
另一个优点是,无论 FOO_GEORGE
是 C 变量还是预处理器宏,它都有效。我正在使用的 C API 使用这两种 API,并且我链接到的同一 API 的不同实现以不同的方式执行,因此独立于它是很好的。
但是,有一个绊脚石:CApiFFI
不能与 ghci 一起使用!问题是 known , 直到 GHC 8.0.1 才会被修复(当我第一次写这篇文章时,它应该是 7.10,然后被推进)。我有一个非常 hacky 的解决方法。 CApiFFI
的工作原理是动态生成一个 C 库,然后针对它编译和链接 Haskell 程序。完成后删除库; ghci 问题似乎是 .so 文件在 ghci 需要链接到它时已经消失了。我只是在编译期间抓取 .c 文件,然后它被删除,然后自己编译它并告诉 ghci 加载它。由于我不经常更改程序的那部分,因此对我来说效果很好。
我捕获临时 .c 文件的方法是在 Emacs compilation-mode
中启动 ghci,使用 (setq compilation -自动跳转到第一个错误 t)
。 Emacs 发现错误并在 GHC 着手删除它之前将 .c 文件加载到缓冲区中 — 当我看到它时,文件已经消失,但我已经在缓冲区中获得了内容。
更新:ghci -fobject-code Foo
有效,但只能看到从模块导出的名称。
关于c - haskell C FFI : accessing static data structures,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25391898/
我正在努力通过接受 void 的 FFI 传递结构并在另一端读回它。 有问题的库是 libtsm,一个终端状态机。它允许您提供输入,然后找出输入后终端将处于哪种状态。 它将其绘制函数声明为: pub
只是为了测试目的,我在 delphi 中创建了一个小的 DLL。代码为: library MyDll; uses SysUtils, Classes, Vcl.Dialogs;
这是我一直好奇的事情:我想知道 LuaJIT 的 FFI 模块如何设法使用正确的调用约定来调用外部 native 函数,而无需在用户原型(prototype)中进行任何声明。 我尝试阅读源代码以自己解
我有一个带有函数的 C 库,在一个不透明的结构上运行,定义如下: Foo* makeFoo(); // create a new Foo Foo* dupFoo(const Foo* orig); /
我正在尝试从 purescript 调用 navigator.geolocation.getCurrentPosition javascript 函数,但遇到了两个问题。 在 javascript 中
ruby 版本 2.2.4p230 RubyGem 版本 2.7.2 已安装 Ruby-devel 和 lib64ffi-devel。 使用 64 位 OpenMandriva 3.0、urpmi 和
我正在尝试使用 FFI 将以下 JavaScript 函数导入 PureScript: function getGreeting() { return "Hi, welcome to the sh
我对 Haskell 中的 FFI 有一些疑问 我知道我必须使用语言编译指示 {-# LANGUAGE ForeignFunctionInterface #-}但是当我使用 {-# LANGUAGE
当我尝试构建 Flutter项目至 IOS 它向我显示了这个错误,我尝试清理并尝试更改项目的目录。 Launching lib/main.dart on iPhone 12 Pro Max in de
完整堆栈跟踪: /Users/galharth/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.5/lib/active_support/dependencie
我试过运行 pod install在我的 Xcode 项目中,但出现以下错误 /System/Library/Frameworks/Ruby.framework/Versions/2.6/us
我需要在节点 Electron 项目中使用模块“ffi”。我可以使用“gyp”重建它并在节点中使用库,但我不能使用“electron-rebuild”重建它并在 Electron 中使用它。 我跑了:
以下警告是什么意思,我该如何解决它的原因? Warning: Unimplemented primitive used:removeEventListener 在 [@bs.val] external
谁能告诉我一个使用带有可变参数的 C 函数(例如 printf )和 Haskell 的外部函数接口(interface)的示例?我尝试搜索 HaskellWiki,但没有找到这样的示例。 谢谢! 最
我使用 FFI 是为了在 C 中使用一个函数,该函数接受一个结构并返回相同的结构。我看到的引用说我必须使用指向这些结构的指针才能将其导入 Haskell。所以,例如。 data Bar = Bar {
我想在带有 FFI 的 Rust 中包含一个动态 C 库。 该库实际上也是用 Rust 构建的,但公开了一个 C 接口(interface),因此它也可以从其他语言中使用。当我用 cargo 构建库(
我试图在winapi上写一个包装器。我想包装接受回调函数指针的函数。 例如,考虑以下情况: // The unsafe callback type the FFI function accepts t
我正在使用 rust-bindgen 从 Rust 访问 C 库。一些函数返回指向结构的可空指针,bindgen 表示为 extern "C" { pub fn get_some_data()
介绍 我正在用 inline-c 包装一个 C 数值库;一些函数可以将回调传递给步骤例程,考虑 ODE 的优化或时间积分。 特别是在原生 C 中,使用回调可以对连续数组进行操作,通过指针修改它们,并将
fn main() { let val = 0; unsafe { foo(&val) } } extern "C" { pub fn foo(val: *const u32)
我是一名优秀的程序员,十分优秀!