使用 GHC 64 位构建的普通 Windows DLL 不会 link
Trivial Windows DLL built with GHC 64-bit does not link
为了概念验证,我想 link 一些琐碎的 Haskell 代码到我的 Visual C++ 应用程序中(使用 Visual Studio 2013)。使用 GHC 7.8.3 32-bit 构建可以工作,但是使用 GHC 7.8.4 64-bit 构建则不行(注意 GHC 中的细微差异版本也一样)。
有3个文件:Grep.hs
和StartEnd.c
是用GHC构建的,形成一个DLL。 main.cpp
是用 Visual Studio 2013 构建的,并尝试在 DLL 库中 link。
我正在构建 DLL:
> ghc -shared -O -optc-O -o Grep.dll StartEnd.c Grep.hs
并且在 Visual Studio 中,我只是 link 反对 Grep.dll.a
并包括 C:\Program Files\MinGHC-7.8.4\ghc-7.8.4\lib\include
,但是 linking 失败
1>main.obj : error LNK2001: unresolved external symbol _HsEnd
1>main.obj : error LNK2001: unresolved external symbol _freegrep
1>main.obj : error LNK2001: unresolved external symbol _grep
1>main.obj : error LNK2001: unresolved external symbol _HsStart
1>C:\Code\Grep\dist\Win32\Release\Grep.exe : fatal error LNK1120: 4 unresolved externals
当我使用 32 位而不是 64 位构建时,完全相同的过程有效。我做错了什么? (我在尝试 link 64 位库时正在构建 64 位应用程序。)
源文件:
Grep.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Grep where
import Foreign
import Foreign.C.String
import Data.List (isInfixOf)
filterlines f = unlines . filter f . lines
grep :: CString -> CString -> IO CString
grep i s = do
ii <- peekCString i
ss <- peekCString s
newCString $ (filterlines (isInfixOf ii)) ss
freegrep :: CString -> IO ()
freegrep s = free s
foreign export ccall grep :: CString -> CString -> IO CString
foreign export ccall freegrep :: CString -> IO ()
StartEnd.c
#include <Rts.h>
void HsStart()
{
int argc = 1;
char* argv[] = {"ghcDll", NULL}; // argv must end with NULL
// Initialize Haskell runtime
char** args = argv;
hs_init(&argc, &args);
}
void HsEnd()
{
hs_exit();
}
main.cpp
#include <HsFFI.h>
#include <Grep_stub.h>
#include <iostream>
extern "C" {
void HsStart();
void HsEnd();
}
int main(int argc, char* argv[])
{
HsStart();
HsPtr str;
str = grep("test", "This is a test\nwith many lines\nand it failed\nand the test passed");
if (str)
{
std::cout << (char*) str;
freegrep(str);
}
HsEnd();
return 0;
}
感谢评论,我将实际的错误输出添加到 post。这让我注意到 Visual Studio 令人困惑的配置管理界面再次咬了我一口。它仍在尝试构建 Win32
版本,即使我的配置设置为 x64
。长话短说,它起作用了!
为了概念验证,我想 link 一些琐碎的 Haskell 代码到我的 Visual C++ 应用程序中(使用 Visual Studio 2013)。使用 GHC 7.8.3 32-bit 构建可以工作,但是使用 GHC 7.8.4 64-bit 构建则不行(注意 GHC 中的细微差异版本也一样)。
有3个文件:Grep.hs
和StartEnd.c
是用GHC构建的,形成一个DLL。 main.cpp
是用 Visual Studio 2013 构建的,并尝试在 DLL 库中 link。
我正在构建 DLL:
> ghc -shared -O -optc-O -o Grep.dll StartEnd.c Grep.hs
并且在 Visual Studio 中,我只是 link 反对 Grep.dll.a
并包括 C:\Program Files\MinGHC-7.8.4\ghc-7.8.4\lib\include
,但是 linking 失败
1>main.obj : error LNK2001: unresolved external symbol _HsEnd
1>main.obj : error LNK2001: unresolved external symbol _freegrep
1>main.obj : error LNK2001: unresolved external symbol _grep
1>main.obj : error LNK2001: unresolved external symbol _HsStart
1>C:\Code\Grep\dist\Win32\Release\Grep.exe : fatal error LNK1120: 4 unresolved externals
当我使用 32 位而不是 64 位构建时,完全相同的过程有效。我做错了什么? (我在尝试 link 64 位库时正在构建 64 位应用程序。)
源文件:
Grep.hs
{-# LANGUAGE ForeignFunctionInterface #-}
module Grep where
import Foreign
import Foreign.C.String
import Data.List (isInfixOf)
filterlines f = unlines . filter f . lines
grep :: CString -> CString -> IO CString
grep i s = do
ii <- peekCString i
ss <- peekCString s
newCString $ (filterlines (isInfixOf ii)) ss
freegrep :: CString -> IO ()
freegrep s = free s
foreign export ccall grep :: CString -> CString -> IO CString
foreign export ccall freegrep :: CString -> IO ()
StartEnd.c
#include <Rts.h>
void HsStart()
{
int argc = 1;
char* argv[] = {"ghcDll", NULL}; // argv must end with NULL
// Initialize Haskell runtime
char** args = argv;
hs_init(&argc, &args);
}
void HsEnd()
{
hs_exit();
}
main.cpp
#include <HsFFI.h>
#include <Grep_stub.h>
#include <iostream>
extern "C" {
void HsStart();
void HsEnd();
}
int main(int argc, char* argv[])
{
HsStart();
HsPtr str;
str = grep("test", "This is a test\nwith many lines\nand it failed\nand the test passed");
if (str)
{
std::cout << (char*) str;
freegrep(str);
}
HsEnd();
return 0;
}
感谢评论,我将实际的错误输出添加到 post。这让我注意到 Visual Studio 令人困惑的配置管理界面再次咬了我一口。它仍在尝试构建 Win32
版本,即使我的配置设置为 x64
。长话短说,它起作用了!