【发布时间】:2021-02-16 23:24:38
【问题描述】:
我尝试将音频库静态链接到我的程序。我使用this灵活包。为了让它运行,我必须按照here 的描述构建 soloud 库。下载后不久,我在“build”文件夹中运行了“genie --with-miniaudio-only --platform=x64 vs2017”,并获得了生成动态和静态库的源代码。现在,我可以从 nimble 包中运行以下演示程序,并附带生成的 dll:
import solouddotnim, times, os
var i, spin = 0
var sl : ptr Soloud
sl = Soloud_create()
discard Soloud_init(sl)
Soloud_setGlobalVolume(sl, 1)
var stream = WavStream_create()
discard WavStream_load(cast[ptr Wav](stream), "test.ogg")
let currentTime = epochTime()
let length = WavStream_getLength(stream)
discard Soloud_play(cast[ptr Soloud](sl), cast[ptr Wav](stream))
while epochTime() - currentTime <= length:
sleep(100)
Soloud_deinit(sl)
Soloud_destroy(sl)
现在到静态链接部分。在我使用的 nimble 包的 solouddotnim.nim 文件中,我看到了这一部分:
when defined(windows):
const
libname* = "libsoloud.dll"
elif ...
所以我简单地将windows部分更改为以下内容,重新安装nimble-package并将“soloud_static_x64.lib”放在testproject的“main.nim”旁边:
when defined(windows):
const
libname* = "soloud_static_x64.lib"
elif ...
但这并没有成功。 (构建时无法打开“soloud_static_x64.lib”错误) 使用常量“libname”的任何地方都有编译指示“cdecl”、“importc”和“dynlib”。例如:
proc Soloud_create*(): ptr Soloud {.cdecl, importc: "Soloud_create", dynlib: libname.}
所以“dynlib”告诉 nim 在 Windows 上使用 dll。但是是静态库的编译指示吗? 在 nim 文档中,我只发现 DynlibOverride 链接到静态库,但我不理解这个例子,这就是我卡住的地方。我尝试了以下方法:
nim c --dynlibOverride:libname --passL:soloud_static_x64.lib "examples\00-ogg\Example00_ogg.nim"
nim c --dynlibOverride:soloudtotnim --passL:soloud_static_x64.lib "examples\00-ogg\Example00_ogg.nim"
首先我不知道 dynlibOverride 期望什么参数,其次都编译,但不工作。它需要与 exe 一起使用的动态库。 我最后一次尝试是从 nimble 包中删除所有 dynlib 编译指示。但是现在我编译不出来了。
undefined reference to `Soloud_create'
...
Error: execution of an external program failed: 'gcc.exe...
我的知识到此结束。有人能帮我吗? 提前致谢。
编辑: 我无法让您的任何解决方案发挥作用。我将问题分解为尽可能小,以便每个人都可以重现: “foo.nim”包含以下内容:
proc add*(a, b: int): int {.cdecl, exportc.} =
a + b
proc sub*(a, b: int): int {.cdecl, exportc.} =
a - b
.lib 是使用以下命令简单生成的:“nim c --app:staticlib foo.nim”
现在为了使用它,我创建了一个包含以下内容的文件“main.nim”:
{.passL:"foo.lib".}
proc add*(a, b: int):int {.cdecl, importc.}
proc sub*(a, b: int):int {.cdecl, importc.}
echo add(10, 5)
echo sub(10, 5)
如果我只是用“nim c -r main.nim”构建它,我会得到以下输出和错误:
P:\Nim\LearnCBinding>nim c -r main.nim
Hint: used config file 'C:\nim-1.5.1\config\nim.cfg' [Conf]
Hint: used config file 'C:\nim-1.5.1\config\config.nims' [Conf]
....CC: stdlib_io.nim
CC: stdlib_system.nim
CC: main.nim
Hint: [Link]
foo.lib(@mfoo.nim.c.o):@mfoo.nim.c:(.text+0x1f6): multiple definition of `PreMainInner'
C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o:@mmain.nim.c:(.text+0x120): first defined here
foo.lib(@mfoo.nim.c.o):@mfoo.nim.c:(.text+0x20a): multiple definition of `PreMain'
C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o:@mmain.nim.c:(.text+0x134): first defined here
foo.lib(@mfoo.nim.c.o):@mfoo.nim.c:(.text+0x240): multiple definition of `NimMainInner'
C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o:@mmain.nim.c:(.text+0x16f): first defined here
foo.lib(@mfoo.nim.c.o):@mfoo.nim.c:(.text+0x254): multiple definition of `NimMain'
C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o:@mmain.nim.c:(.text+0x183): first defined here
foo.lib(@mfoo.nim.c.o):@mfoo.nim.c:(.text+0x285): multiple definition of `main'
C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o:@mmain.nim.c:(.text+0x1b4): first defined here
foo.lib(@mfoo.nim.c.o):@mfoo.nim.c:(.text+0x2da): multiple definition of `NimMainModule'
C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o:@mmain.nim.c:(.text+0x209): first defined here
collect2.exe: error: ld returned 1 exit status
Error: execution of an external program failed: 'C:\nim-1.5.1\dist\mingw64\bin\gcc.exe -o P:\Nim\LearnCBinding\main.exe C:\Users\Peter\nimcache\main_d\stdlib_io.nim.c.o C:\Users\Peter\nimcache\main_d\stdlib_system.nim.c.o C:\Users\Peter\nimcache\main_d\@mmain.nim.c.o foo.lib '
由于多重定义错误,我也尝试使用参数“--noMain:on”构建 foo.lib,但没有任何区别。
你有同样的问题吗?顺便说一句,我使用当前版本的 Nim“nim-1.5.1”并使用来自 nim 的 finish.exe 重新安装了 MingW。
【问题讨论】:
-
使用 passC 将选项传递给 C 编译器,使用 passL 将选项传递给链接器。有 clib 链接 C 库。 Yopu 几乎可以将库与您在 C 中使用它做的完全一样。
-
如果您还没有找到它,它会记录在手册中;) nim-lang.org/docs/….
-
谢谢。但我没有那么多经验。这对绑定意味着什么?我是否必须用“passc”和“link”pragma(如
{.link: "soloud_static_x64.lib", passc:"-L soloud_static_x64".})替换所有“dynlib”pragma? -
删除所有 {.dynlib.},保留 {.importc.} 并添加一个链接库的单个 {.passL.}。
-
现在它看起来像一个错误。我在这里报告了它forum.nim-lang.org/t/7080。在这些答案之后,我在这里打开了一个错误报告github.com/nim-lang/Nim/issues/15955
标签: static-libraries static-linking nim-lang