这是一个如何解决
VStudio C (和 C++) 运行时库 (
VCRTLib 或
UCRT - 请参阅
[SO]: 如何规避 Windows 通用 CRT 标头对 vcruntime.h 的依赖 (@CristiFati's answer)) 在您的项目和
LibProtoBuf 项目中使用不匹配的问题。让我详细说明一下:
假设有一些
C (
C++) 代码,其目的是要运行。可以通过以下方式实现:
直接:将该代码包含在一个VC应用程序类型的项目中 - 这将生成一个.exe文件。
间接:将代码包含在VC库类型的项目中 - 这将生成一个库,只能在被另一个.exe文件(调用该库的文件)调用时运行。该库可以是:
静态的:所有的C(C++)代码将被编译并存储在一个.lib文件中。在使用该库时(无论是应用程序还是库),需要在链接时使用该文件。请注意,你的.lib文件中的所有所需代码都将被“复制”到其他项目中。
动态的:现在你将有两个文件:一个.dll文件,其中包含已编译(和链接)的代码,以及一个.lib文件(1),其中包含指向.dll文件中代码的“指针”。在另一个项目中使用该库时,你还需要在链接时使用.lib文件,但现在它不会包含代码,因此不会将其复制到其他库中(其他库将更小),但在运行时,其他库将需要.dll文件。
您可以查看
[SO]: LNK2005错误在CLR Windows表单中(@CristiFati的答案),了解有关如何将
C (
C++)代码转换为可执行格式的详细信息。此外,
Google上有很多关于静态库和动态库之间差异以及何时使用它们的文章,例如
[SO]:何时使用动态库与静态库的示例。
正如您猜测的那样,
CRT或
C运行时库(其中包含使
C代码能够运行的底层系统 - 一个例子是内存管理函数:
malloc,
free)也不例外 - 它相当于
Nix的
libc.a(静态或档案)与
libc.so(动态或共享对象)-但在
VStudio中要复杂一些:
注:
现在,
UCRT部件不像其他库一样被包含在项目中(
项目属性 -> 链接器 -> 输入 -> 附加依赖项),但由于它们的性质(静态或动态)需要在编译时配置,因此它们从
[MS.Docs]: /MD、/MT、/LD(使用运行时库)配置,有4个可用选项:
多线程(/MT)
多线程调试(/MTd)
多线程 DLL(/MD)
多线程调试 DLL(/MDd)
显然,包含“Debug”的是在构建
Debug配置时使用的,而其他的则是针对
Release的;关键点是那些具有
DLL的是使用
动态运行时版本,而另一些则是使用
静态版本。
回到您的错误:链接器抱怨main.obj(项目的一部分)具有MDd_DynamicDebug(链接到动态调试版本),而common.obj(LibProtoBuf项目的一部分)具有MTd_StaticDebug(链接到静态调试版本),因此您在同一个可执行文件(或.dll)中链接了2个运行时 - 这是不可能的。
为了解决这个问题,您应该确保
LibProtoBuf和您的主项目对于
UCRT拥有相同的值。
当然,更简单的方法是将您的主项目设置更改为与
LibProtoBuf相匹配的设置,但即使需要重新编译
LibProtoBuf(如果更改该选项会生成使
LibProtoBuf非常难以构建的错误,并且您的项目将保持这么简单),也建议使用动态运行时版本(在涉及到
.dll的大型项目中可能会变得混乱)。
注意:不要将
UCRT类型(静态/动态)与
LibProtoBuf正在构建的方式(目前为静态,但我确定它也可以构建为动态)混淆。
更新 #0
补充一些有关上述注释的额外信息,因为一些评论要求提供这些信息,而且对其他用户可能也有用。
关于库(包括LibProtoBuf )有两个方面是完全不相关的:
库类型(构建方式):动态 / 静态
UCRT类型(使用UCRT的方式):同样是动态 / 静态
因此,有4个完全有效的组合:
使用动态UCRT 的动态库
使用静态UCRT 的动态库
使用动态UCRT 的静态库
使用静态UCRT 的静态库
对于LibProtoBuf,每个方面都由一个布尔型的CMake选项控制:
- 库类型:protobuf_BUILD_SHARED_LIBS
- UCRT类型:protobuf_MSVC_STATIC_RUNTIME
这2个标志可以通过以下方式之一设置:
以上4种组合因此在v3.5中是
可能的,但是
第2种组合默认被禁用(指定
-Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_MSVC_STATIC_RUNTIME=ON
将构建一个链接到
动态UCRT的.dll),以避免可能的运行时问题,启用它需要手动干预。
关于构建说明的更多详细信息(通过cmake),请查看:
[GitHub]:protocolbuffers/protobuf - (master) protobuf/cmake/README.md。
脚注
libprotobuf
的静态版本(_.lib_),现在您正在尝试将其链接到您的VStudio应用程序中? - CristiFati