我正在尝试从我的 Haskell 代码构建一个 Windows DLL。应该从 C# 中的托管代码调用此 DLL 中的函数。并且,至少有一个函数(在 c# 代码中定义)将从此 DLL 中的函数调用。
冒着过度解释的风险,这里有一个小图来描述我想要的:
+----------------------+ +------------------------+
| Managed C# code | | Haskell code (in DLL) |
| | (1) | |
| fn_calling_hs() -----------------> fn_called_from_cs() |
| | | |
| | | |
| fn_called_from_hs() <--------------- fn_calling_cs() |
| | (2) | |
+----------------------+ +------------------------+
我设法使(1)完美地工作,即DLL中的Haskell函数由C#代码调用,结构和数组的编组正确,Haskell中函数执行的结果也是正确的。到现在为止还挺好。
问题在于(2),即来自 Haskell(在 DLL 中)的函数调用 C# 中定义的托管函数。问题出在构建本身 - 我还没有真正检查 (2) 的结果。
由于 c# 托管代码中的 fn_call_from_hs() 是在 C# 中定义的,因此我在 Haskell 代码(在 DLL 中)中只有“导入”的函数符号:
foreign import ccall fn_called_from_hs :: IO CString
现在,当我使用堆栈构建我的 Haskell 项目时,它构建 Haskell DLL 没有问题,但构建继续也链接“main.exe” - 这失败(显然),因为在任何地方都没有定义函数 fn_call_from_hs() Haskell 代码(在 c# 中定义)。
在构建 HsDLL.dll 后,有什么方法可以阻止堆栈继续构建 main.exe?我对具有未解析符号 (fn_call_from_hs()) 的 HsDLL.dll 没问题,因为在托管 C# 代码加载此 DLL 期间,运行时链接器将找到此符号。
到目前为止,我已经尝试了这些步骤,但没有一个有帮助:
- 从 package.yaml 中删除了“可执行文件”和“测试”
添加了 GHC 选项:
-no-hs-main
在 package.yaml 中。包含 HsDLL 构建的 package.yaml 部分如下所示:library: source-dirs: - src - src/csrc include-dirs: src/csrc ghc-options: - -shared - -fno-shared-implib - -no-hs-main
- 完全删除了 Main 模块(即,从“app”文件夹中删除了由堆栈自动创建的 Main.hs)
- 我
-dynamic
在 ghc-options 中添加了该标志,希望 GHC 会假设未解析的符号将在其他地方定义,但这带来了其他问题:GHC 现在抱怨它需要“dyn”base 库等。
所以,最后,我总是这样结束:
PS C:\workspace\Haskell\hscs\src\csrc> stack build
hscs-0.1.0.0: configure (lib)
Configuring hscs-0.1.0.0...
hscs-0.1.0.0: build (lib)
Preprocessing library for hscs-0.1.0.0..
Building library for hscs-0.1.0.0..
Linking main.exe ...
.stack-work\dist\5c8418a7\build\HsLib.o:fake:(.text+0x541): undefined reference to `fn_called_from_hs'
collect2.exe: error: ld returned 1 exit status
`gcc.exe' failed in phase `Linker'. (Exit code: 1)
-- While building custom Setup.hs for package hscs-0.1.0.0 using:
C:\tools\HaskellStack\setup-exe-cache\x86_64-windows\Cabal-simple_Z6RU0evB_2.0.1.0_ghc-8.2.2.exe --builddir=.stack-work\dist\5c8418a7 build lib:hscs --ghc-options " -ddump-hi -ddump-to-file -fdiagnostics-color=always"
Process exited with code: ExitFailure 1
所以,我的问题是:(1)我完全不知道如何停止链接“main.exe”!我知道函数 fn_call_from_hs() 没有在 HsDLL 中定义,但是,正如我所说,我没问题,因为它是在托管 c# 代码中定义的。我只想不构建 main.exe。
或者
(2) 我是否应该继续-dynamic
向 GHC 添加标志(保持所有其他标志如上所述)?在这种情况下,我如何获得堆栈来安装 GHC 抱怨的“dyn”库?
有人可以帮助我吗?提前感谢您耐心阅读这个(相当长的)问题!