【问题标题】:Haskell FFI: Interfacing with simple C++?Haskell FFI:与简单的 C++ 接口?
【发布时间】:2012-09-18 11:03:32
【问题描述】:

从我目前所读到的内容来看,将 FFI 与 C++ 一起使用是非常困难的。最大的原因之一似乎是将 C++ 对象转换为 Haskell。我现在的问题是我对 C 没有任何经验,但是有几年的 C++ 经验,而且我更喜欢 OOP。因此,我自然希望从 C++ 中受益。

那么,我可以编写供 Haskell FFI 使用的 C++ 程序来解决这些问题吗? C++ 可以在后台做任何事情,但 API 将类似于 C,即我没有交换对象,没有重载的顶级函数等等。有什么需要注意的陷阱吗?

(将我的项目与您可能熟悉的项目进行比较:考虑使用 SciPy 的 Weave 来加速 Python 代码。)

【问题讨论】:

  • 如果你想使用 C++,那么使用 C++,而不是 Haskell。否则保留 FFI 用于与本机库和 maaaaaybe 真正性能关键代码的接口。
  • @CatPlusPlus 性能关键代码正是我使用 C++ 的目的。
  • FFI 被用作最后的手段。
  • 是的。我们现在可以专注于我的问题了吗?
  • 答案是'是的,如果你小心的话,你可以使用 extern "C"-d 函数',并且与 Haskell 没有真正的关系。

标签: c++ haskell ffi


【解决方案1】:

是的,如果您在 C++ 代码之上公开 C API,则可以通过 FFI 使用 C++ 代码。

一种常见的模式是将一个类的所有“方法”简单地包装为 C 过程,这样该类的对象可以被视为可以应用这些函数的不透明指针。

例如,给定代码 (foo.h):

class foo
{
public:
  foo(int a) : _a(a) {}
  ~foo() { _a = 0; } // Not really necessary, just an example

  int get_a() { return _a; }
  void set_a(int a) { _a = a; }

private:
  int _a;
}

...您可以轻松创建所有这些方法的 C 版本 (foo_c.h):

#ifdef __cplusplus
typedef foo *foo_ptr;
extern "C"
{
#else
typedef void *foo_ptr;
#endif

foo_ptr foo_ctor(int a);
void foo_dtor(foo_ptr self);

int foo_get_a(foo_ptr self);
void foo_set_a(foo_ptr self, int a);
#ifdef __cplusplus
} /* extern "C" */
#endif

那么,肯定有一些通过C++接口(@98​​7654325@)实现C接口的适配器代码:

#include "foo.h"
#include "foo_c.h"

foo_ptr foo_ctor(int a) { return new foo(a); }
void foo_dtor(foo_ptr self) { delete self; }

int foo_get_a(foo_ptr self) { return self->get_a(); }
void foo_set_a(foo_ptr self, int a) { self->set_a(a); }

标题 foo_c.h 现在可以包含在 Haskell FFI 定义中。

【讨论】:

  • 为什么在 C 中使用 void *? typedef struct foo* foo_ptr; 两者都适用。
  • 因为foo 是一个类而不是一个结构,而且如果你有一个支持 C++ 的 C 编译器可以让你做到这一点,那么它是非常不标准的。
  • 当您在某些 typedef 中将 class foo 寻址为 struct foo 时,每个符合标准的 C++ 编译器都必须对其进行编译。
  • 是的,但我不会用 C++ 编译器编译 C 代码,尤其是当 Cabal 自动调用 C 编译器时。
  • 你显然在代码中有#ifdef __cplusplus,所以你显然用两个编译器编译它,typedef struct foo* foo_ptr; 在两个编译器中编译成foo 的指针。您不能在 C 中定义 foo,因此您不能在 C 中取消引用指向 foo 的指针(或使用它进行指针运算),但您也不能使用 void*
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 2010-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多