如何在OS X中包含FFI?

时间:2018-01-17 19:42:51

标签: c include closures

我在启用FFI扩展程序的情况下构建this project时遇到问题。为了隔离问题,我正在尝试编译this example(下面全部包含)。

我正在使用OS X 10.13.2,安装了命令行工具的Xcode 9.2(确认存在 /usr/include/ffi/ffi.h )。我修改了示例,因此include行读取include <ffi/ffi.h>

在没有选项的情况下调用编译器,我得到以下结果:

$ gcc closure.test.c
closure.test.c:23:13: warning: implicit declaration of function 'ffi_closure_alloc' is invalid in C99 [-Wimplicit-function-declaration]
  closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);
            ^
closure.test.c:23:11: warning: incompatible integer to pointer conversion assigning to 'ffi_closure *' (aka 'struct ffi_closure *') from
      'int' [-Wint-conversion]
  closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);
          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
closure.test.c:35:15: warning: implicit declaration of function 'ffi_prep_closure_loc' is invalid in C99 [-Wimplicit-function-declaration]
          if (ffi_prep_closure_loc(closure, &cif, puts_binding,
              ^
closure.test.c:45:3: warning: implicit declaration of function 'ffi_closure_free' is invalid in C99 [-Wimplicit-function-declaration]
  ffi_closure_free(closure);
  ^
4 warnings generated.
Undefined symbols for architecture x86_64:
  "_ffi_closure_alloc", referenced from:
      _main in closure-7b0e9b.o
  "_ffi_closure_free", referenced from:
      _main in closure-7b0e9b.o
  "_ffi_prep_cif", referenced from:
      _main in closure-7b0e9b.o
  "_ffi_prep_closure_loc", referenced from:
      _main in closure-7b0e9b.o
  "_ffi_type_pointer", referenced from:
      _main in closure-7b0e9b.o
  "_ffi_type_sint32", referenced from:
      _main in closure-7b0e9b.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我需要哪些选项/修改来纠正这个问题?

closure.test.c的来源:

#include <stdio.h>
#include <ffi.h>

/* Acts like puts with the file given at time of enclosure. */
void puts_binding(ffi_cif *cif, void *ret, void* args[],
                  void *stream)
{
  *(ffi_arg *)ret = fputs(*(char **)args[0], (FILE *)stream);
}

typedef int (*puts_t)(char *);

int main()
{
  ffi_cif cif;
  ffi_type *args[1];
  ffi_closure *closure;

  void *bound_puts;
  int rc;

  /* Allocate closure and bound_puts */
  closure = ffi_closure_alloc(sizeof(ffi_closure), &bound_puts);

  if (closure)
    {
      /* Initialize the argument info vectors */
      args[0] = &ffi_type_pointer;

      /* Initialize the cif */
      if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1,
                       &ffi_type_sint, args) == FFI_OK)
        {
          /* Initialize the closure, setting stream to stdout */
          if (ffi_prep_closure_loc(closure, &cif, puts_binding,
                                   stdout, bound_puts) == FFI_OK)
            {
              rc = ((puts_t)bound_puts)("Hello World!");
              /* rc now holds the result of the call to fputs */
            }
        }
    }

  /* Deallocate both closure, and bound_puts */
  ffi_closure_free(closure);

  return 0;
}

3 个答案:

答案 0 :(得分:2)

npm install 为我工作了一个额外的步骤。当您运行 npm run dev 时,您将看到以下内容:

brew install libffi

导出这些环境变量可以让 rvm 正常工作。

答案 1 :(得分:1)

好吧,好像你可以解决这个问题:

$ cd
$ git clone https://github.com/libffi/libffi
$ cd libffi/
$ ./autogen.sh
$ ./configure
$ make
$ make install

这将从源代码构建libffi,即使您从libffi安装了brew,它也会正常运行,因为这个新版本将安装在/usr/local下,而不是Cellar

然后您无需更改#include,保持#include <ffi.h>,打开终端到您隔离的c源所在的文件夹并发出gcc -o ffi -lffi ffi.c(假设它是来源)你有文件。)

teixeira: ~/etudes_c $ ./ffi
Hello World!

答案 2 :(得分:1)

brew install libffi 是帮助我解决 ld 问题的快速解决方案。