在 ghci 中从 c 源调用动态库失败

Posted

技术标签:

【中文标题】在 ghci 中从 c 源调用动态库失败【英文标题】:Calling dynamic libraries from c-sources fails in ghci 【发布时间】:2016-06-10 03:52:06 【问题描述】:

我有一些来自动态库的 C 函数(这里只是 zlibVersion),我想从 cabal 包中的捆绑 C 代码中调用它们。在这里,我直接将其称为外部导入,并通过捆绑的 C 代码间接调用它,以表明后者会导致 ghci 崩溃,即使在前者成功之后也是如此。

Main.hs:

module Main (main) where

import Foreign.C.String (CString, peekCString)

foreign import ccall "foreign_test" foreignTest :: IO ()
foreign import ccall "zlibVersion" zlibVersion :: IO CString

main :: IO ()
main = do
  zlibVersion >>= peekCString >>= putStrLn
  foreignTest

foreign_test.c:

#include <stdio.h>
#include <zlib.h>

void foreign_test() 
    puts(zlibVersion());

从已编译的二进制文件中可以正常工作:

$ cabal build
$ dist/build/cabal-extra-libs-test/cabal-extra-libs-test
1.2.5
1.2.5

但是间接调用会导致 ghci 崩溃:

$ cabal repl
Preprocessing executable 'cabal-extra-libs-test' for
cabal-extra-libs-test-0.1.0.0...
GHCi, version 7.10.3: http://www.haskell.org/ghc/  :? for help
[1 of 1] Compiling Main             ( Main.hs, interpreted )
Ok, modules loaded: Main.
*Main> main
1.2.5
dyld: lazy symbol binding failed: Symbol not found: _zlibVersion
  Referenced from: /var/folders/pz/920gzhqn01q8d6vjkvy1yvdr0000gn/T/ghc6850_0/libghc_1.dylib
  Expected in: flat namespace

dyld: Symbol not found: _zlibVersion
  Referenced from: /var/folders/pz/920gzhqn01q8d6vjkvy1yvdr0000gn/T/ghc6850_0/libghc_1.dylib
  Expected in: flat namespace

cabal-extra-libs-test.cabal:

name:                cabal-extra-libs-test
version:             0.1.0.0
build-type:          Simple
cabal-version:       >=1.10

executable cabal-extra-libs-test
  default-language: Haskell2010
  main-is: Main.hs
  build-depends: base

  c-sources: foreign_test.c
  extra-libraries: z

GHC 是 7.10.3,在 OS X 10.11.5 上安装 cabal-install 1.24.0.0。使用 stack 和 stack ghci 构建会产生相同的崩溃。

【问题讨论】:

【参考方案1】:

这很奇怪.. 我对 OSX 了解不多,但dyld: lazy symbol binding failed: Symbol not found: _zlibVersion 给人的印象是它认为 OSX 是一个下划线平台(例如,一个 C 函数被 _ 破坏的平台)。

这是标准的 GHC 构建吗?你可以试试8.0.1吗?链接器中的很多已更改。

【讨论】:

nm 的输出来看,OS X 确实在符号上使用了下划线前缀。 7.10.3 构建来自堆栈,我认为它使用官方 GHC 构建。 GHC 8.0.1 确实可以正常工作!

以上是关于在 ghci 中从 c 源调用动态库失败的主要内容,如果未能解决你的问题,请参考以下文章

怎么调用动态链接库函数?

Java调用C++动态链接库dll,有详细过程。VS2015+Eclipse以及失败解决方案

Android怎么调用第三方SO动态链接库

VC++ 解决dll库动态库加载失败问题(调用LoadLibrary加载失败)(附源码)

VS2012编译的DLL动态库为啥在VS2012上调用正常,在VS2008上使用失败

C 语言动态库封装与设计 ( Windows 动态库简介 | Visual Studio 调用动态库 )