【问题标题】:How to include FFI in OS X?如何在 OS X 中包含 FFI?
【发布时间】:2018-01-17 19:42:50
【问题描述】:

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

我正在使用安装了命令行工具的 OS X 10.13.2、Xcode 9.2(确认 /usr/include/ffi/ffi.h 存在)。我修改了示例,因此包含行显示为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;
}

【问题讨论】:

  • 坏消息:Mac OS 确实没有您缺少的功能。查看this,尤其是闭包分配部分。
  • @user58697 很奇怪,真的吗?我看到在 MacOS 上缺少 ffi_prep_cif_var 的一些佐证。但是闭包似乎是存在的...关于 MacOS 上闭包中当前错误的讨论...例如this one 最近提到它,ffi_closure_alloc 被称为here in 2009。他们在谈论不同的事情吗?
  • bugs.python.org/msg115649 是更多的证据。

标签: c include closures


【解决方案1】:

好吧,看来您可以这样做:

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

这将从源代码构建libffi,即使您从brew 安装了libffi,它也可以工作,因为这个新版本将安装在/usr/local 下而不是Cellar 下。

那么你不需要更改#include,保持它像#include &lt;ffi.h&gt;,打开一个终端到你隔离的c源所在的文件夹并发出gcc -o ffi -lffi ffi.c(假设它是你拥有的源文件)。

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

【讨论】:

  • 我收到以下错误:Undefined symbols for architecture x86_64: "_ffi_closure_alloc", referenced from: _main in closure-77e81a.o "_ffi_closure_free", referenced from: _main in closure-77e81a.o "_ffi_prep_closure_loc", referenced from: _main in closure-77e81a.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
  • 我告诉你的程序的哪一步会出现这个错误?
  • 在构建点:gcc -o ffi -lffi ffi.c — 仔细检查,预先运行所有步骤。
  • 你把#include改成#include &lt;ffi.h&gt;了吗?
【解决方案2】:

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

# For compilers to find libffi you may need to set:
  export LDFLAGS="-L/opt/homebrew/opt/libffi/lib"
  export CPPFLAGS="-I/opt/homebrew/opt/libffi/include"

# For pkg-config to find libffi you may need to set:
  export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig"

导出这些环境变量允许 rvm 正常工作。

【讨论】:

  • 这行得通,但我不需要导出环境变量。
  • 这对我有用 export PKG_CONFIG_PATH="/opt/homebrew/opt/libffi/lib/pkgconfig" gem install ffi
【解决方案3】:

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

【讨论】:

  • 这行得通。我不需要将环境变量导出为mentioned here
猜你喜欢
  • 2014-11-17
  • 2013-11-04
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
  • 2012-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多