从我到目前为止所读到的内容来看,使用带有C的FFI非常难以实现.其中一个最大的原因似乎是将C对象转换为
Haskell.我现在的问题是我没有任何C经验,但用C几年,我也更喜欢OOP.因此,我自然希望从C中受益.
那么我可以编写设计用于Haskell FFI的C程序来解决这些问题吗? C可以做任何事情,但API会像C一样,即我没有交换对象,没有超载的顶级函数等等.是否有任何陷阱需要注意?
解决方法
是的,如果在该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接口(foo_c.cpp)实现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定义中.