微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

nim:使用静态库

如何解决nim:使用静态库

我试图将音频库静态链接到我的程序。我使用this敏捷包。为了使其运行,我不得不按照here的描述构建一个声音库。下载后不久,我在“ build”文件夹中运行了“ genie --with-miniaudio-only --platform = x64 vs2017”,并获取生成动态库和静态库的源代码。现在,我可以从带有生成的dll的nimble包中运行以下演示程序:

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)

现在到静态链接部分。在我使用的灵活软件包的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”的Everey处有编译指示“ 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旁边有一个动态库。 我的最后尝试是从灵活的软件包中删除所有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,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,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。

解决方法

我会尽力帮助您解决以下错误:

undefined reference to `Soloud_create'

但我会假设你已经配置了你的环境,所以你可以用visual studio编译器编译你的nim程序(通过在你的编译命令中添加--cc:vcc) 这是因为您似乎已经拥有 Visual Studio 2017,并且正在用它编译 soloud 静态库。我认为当您同时使用一个编译器进行编译时,这是最佳选择:静态库和将使用它的可执行文件。

用一些文本/十六进制编辑器打开你的静态库(soloud_static_x64.lib)并搜索“Soloud_create”。我想你不会找到任何东西。那是为什么?因为出于某种原因,作者决定不在静态库项目中包含“C 接口”。所以它只包含 C++ 符号,而不包含我们 solouddotnim.nim 模块所需的纯 C 符号。

让我们试着找出我们需要的 .cpp 文件。我在 Soloud 的官方网站上注意到了这个信息 - http://sol.gfxile.net/soloud/c_api.html
所以我想我们只需要一个文件: soloud_c.cpp
让我们尝试将它包含在您使用 Genie 生成的 SoloudStatic.vcxproj 文件中。像这样:

..
<ClCompile Include="..\..\src\c_api\soloud_c.cpp">
</ClCompile>
..

并重新编译我们的静态库。我在powershell中使用这个命令:

& 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin\MSBuild.exe' /p:PlatformToolset=v142`;WindowsTargetPlatformVersion=10`;Configuration=Release`;Platform=x64 .\SoloudStatic.vcxproj

但是您可以根据需要进行编译。只要确保它的架构是真正的 x64。你可以用这个命令检查它:

dumpbin /headers soloud_static_x64.lib | more

最后将它与您的 nim 文件链接起来。将此行添加到顶部:

{.link:"soloud_static_x64.lib".}

并使用以下命令编译 nim 文件:

nim c --cc:vcc --dynlibOverride:libsoloud.dll -r "examples\00-ogg\Example00_ogg.nim"

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。