【问题标题】:Link error on Visual Studio 2015 when using library built on Visual Studio 2019使用基于 Visual Studio 2019 构建的库时,Visual Studio 2015 上的链接错误
【发布时间】:2021-02-10 17:49:03
【问题描述】:

我在 Visual Studio 2019(使用平台工具集 v142)上将 OpenCV 编译为静态库,然后编写了一个链接 opencv 库的演示程序,一切正常。但是当我在 Visual Studio 2015(使用平台工具集 v140)上编译演示时,它抱怨链接错误:

1>------ Build started: Project: parvati_demo, Configuration: Release Win32 ------
1>opencv_imgproc342.lib(resize.obj) : error LNK2019: unresolved external symbol ___libm_sse2_sincos_ referenced in function "void __cdecl cv::interpolateLanczos4(float,float *)" (?interpolateLanczos4@cv@@YAXMPAM@Z)
1>E:\CPPCode\projects\parvati_release1\build32\Release\parvati_demo.exe : fatal error LNK1120: 1 unresolved externals
2>------ Skipped Build: Project: ALL_BUILD, Configuration: Release Win32 ------
2>Project not selected to build for this solution configuration 
========== Build: 0 succeeded, 1 failed, 1 up-to-date, 1 skipped ==========

据此page;在 Visual Studio 2015/17/19 中确保二进制兼容性:
我发现函数cv::interpolateLanczos4被定义为

static inline void interpolateLanczos4( float x, float* coeffs )
{
    static const double s45 = 0.70710678118654752440084436210485;
    static const double cs[][2]=
    {{1, 0}, {-s45, -s45}, {0, 1}, {s45, -s45}, {-1, 0}, {s45, s45}, {0, -1}, {-s45, s45}};

    if( x < FLT_EPSILON )
    {
        for( int i = 0; i < 8; i++ )
            coeffs[i] = 0;
        coeffs[3] = 1;
        return;
    }

    float sum = 0;
    double y0=-(x+3)*CV_PI*0.25, s0 = std::sin(y0), c0= std::cos(y0);
    for(int i = 0; i < 8; i++ )
    {
        double y = -(x+3-i)*CV_PI*0.25;
        coeffs[i] = (float)((cs[i][0]*s0 + cs[i][1]*c0)/(y*y));
        sum += coeffs[i];
    }

    sum = 1.f/sum;
    for(int i = 0; i < 8; i++ )
        coeffs[i] *= sum;
}

其中std::sin()std::cos()使用,在corecrt_math.h中声明。所以,我猜想错过的符号与libmxxxcrt.lib 有关。最后,我在 Windows 10 SDK 中找到了一个ucrt.lib,但它也不起作用。谁能帮帮我?

【问题讨论】:

  • 推测,__libm_sse2_sincos_ 是一个使用 SSE 的特殊实现,它根据目标架构上存在的可用特性进行编译。您似乎在没有 SSE 支持的情况下编译了库,但现在针对的是使用 SSE 的体系结构。您需要强制您的库包含 SSE 版本以解析链接器导入。

标签: c++ windows visual-studio visual-studio-2015 linker-errors


【解决方案1】:

您误解了 Microsoft 解释的二进制兼容性的范围。跨编译器版本兼容的是与任何版本的 C++ 运行时的最终可执行文件(和相关联的 DLL)。 IE。您可以使用 VS2019 编译您的应用程序,并使用 VS2017/15 附带的 C++ 运行时库可再发行包。仅当您使用dynamically-linked runtime 时,您才会关心这一点。在实践中,这意味着如果出于某种原因您发布了一些使用 VS2015/v140 工具集编译的可执行文件和一些使用 VS2017/v141 工具集编译的可执行文件,您只需要让用户安装一个 C++ 运行时可再发行文件。如果您不控制系统上存在的 C++ 运行时的确切版本,这是一个巨大的优势(在某些接受第三方插件的嵌入式系统中可能会出现这种情况,这些插件必须作为 DLL 分发并且无法安装其他插件)资产)。

但是,构成这个最终可执行文件的所有目标文件仍然需要使用相同的编译器主版本进行编译。如果你使用full program optimisation,你甚至需要有匹配的次要编译器版本。一般来说,对于 C++ 应用程序,强烈建议确保构成最终二进制文件(包括关联的 DLL)的所有翻译单元都使用完全相同的编译器进行编译。

编辑:

这是整个程序优化文档的引述,它强调了链接使用不同 VS 版本编译的库在某些情况下可能不起作用的事实:

在当前版本中使用 /GL 生成的文件格式可能无法被后续版本的 Visual C++ 读取。您不应发布由使用 /GL 生成的 .obj 文件组成的 .lib 文件,除非您愿意为您希望用户现在和将来使用的所有 Visual C++ 版本提供 .lib 文件的副本。

【讨论】:

  • 它确实说您可以链接使用不同工具集版本构建的库(和目标文件)。
  • 我怀疑您可以将使用 v141 工具集的库与使用 v142 工具集的可执行文件链接起来,只要两者都是使用相同的编译器编译的,即使我不明白您为什么要这样做。
猜你喜欢
  • 2021-04-16
  • 1970-01-01
  • 1970-01-01
  • 2015-03-30
  • 1970-01-01
  • 2016-03-21
  • 1970-01-01
  • 2021-09-12
  • 2020-09-19
相关资源
最近更新 更多