我需要构建一些 C 代码,然后通过 FFI 引用该 C 代码。我想在 osx 的 ghci 内部使用我的绑定。我的一个限制是我不能只将 C 源代码交给 .cabal 文件中的 ghc。这是由于 ghc/cabal 的限制可能会在 ghc 的下一个版本中修复(但我希望我的代码现在可以在旧版本上工作)。有关详细信息,请参阅此错误。
该错误的要点是 C 代码需要使用一些 Objective-C 模块进行编译,而 ghc 将它们误解为链接器脚本。我已经尝试了很多事情,并且使用makefile自己构建文件是唯一有效的方法。真的,这不应该是一个问题,因为它应该与我决定使用我没有自己构建的外部 C 库一样。为了解决这个问题,让我们假设它是一个单独的 C 库,我可以使用不同的选项轻松地重建它。
如果我将 C 库构建为 .a,则 ghci 抱怨它无法打开 .dylib。我的第一个问题是:为什么 ghci 需要一个 .dylib 并且它真的使用它吗?
当我构建 dylib时,将代码加载到 ghci 时出现段错误。
请记住,这个绑定已经在其他平台上工作,包括 linux 和 windows,当我编译而不是使用 ghci 时,绑定在 osx 上工作正常。此问题特定于 osx/ghci 组合。
在上面的那个跟踪中,我正在使用 gdb,但无论我是否使用 gdb,它都会崩溃。我将其追踪到导致崩溃的行:
void _glfwClearWindowHints( void )
{
memset( &_glfwLibrary.hints, 0, sizeof( _glfwLibrary.hints ) );
}
麻烦制造者是 memset 行,实际上问题是在 ghci 内部运行时写入提示结构_glfwLibrary
是内存访问冲突。提示结构只是一堆整数。它非常平坦和简单,因此我认为问题出在我如何链接事物或 ghci 加载代码的方式上。
以下是我用来构建 dylib 和 .a 的 makefile 的一些内容:
GCCFLAGS := $(shell ghc --info | ghc -e "fmap read getContents >>= \
putStrLn . unwords . read . Data.Maybe.fromJust . lookup \
\"Gcc Linker flags\"")
FRAMEWORK := -framework Cocoa -framework OpenGL
GLFW_FLAG := $(GCCFLAGS) -O2 -fno-common -Iglfw/include -Iglfw/lib \
-Iglfw/lib/cocoa $(CFLAGS)
all: $(BUILD_DIR)/static/libglfw.a $(BUILD_DIR)/dynamic/libglfw.dylib
$(BUILD_DIR)/dynamic/libglfw.dylib: $(OBJS)
$(CC) -dynamiclib -Wl,-single_module -compatibility_version 1 \
-current_version 1 \
$(GLFW_FLAG) -o $@ $(OBJS) $(GLFW_SRC) $(FRAMEWORK)
$(BUILD_DIR)/static/libglfw.a: $(OBJS)
ar -rcs $@ $(OBJS)
大多数标志直接取自 GLFW Makefile,所以我认为它们对于该库应该是正确的。
第一行看起来有点奇怪,但这是我用来解决这个问题的解决方案。
平台详情:
- OSX 10.6.6
- x86_64
- 4核
- 通过 Haskell 平台安装程序安装的 GHC 版本 7.0.3
- 源码仓库:https ://github.com/dagit/GLFW-b
编辑:这是我的问题:
- 这应该与 ghci 一起使用吗?
- 如果是这样,我做错了什么或如何修复崩溃?
- 我可以通过 ghci 使用静态 .a 版本的库吗?