将google protobuf静态链接到dll库中

9
在安装和使用Google Protobuf库的指导页面上(在Windows上安装Protobuf),它指出:
如果您的项目本身是供第三方软件使用的DLL,则建议不要在库的公共接口中公开协议缓冲区对象,并且将协议缓冲区静态链接到库中。
我想知道如何实现这一点。据我所知,您可以通过两种方式构建Google Protobuf:静态和动态。
如果您以动态方式构建它,则会遇到上述问题。如果您以静态方式构建它,则使用Visual Studio的代码生成类型多线程(/MT)。这意味着在我的dll lib中(其中使用多线程DLL(/MD)构建),您将获得以下链接器错误:
错误LNK2038:在Emulator.obj中检测到“RuntimeLibrary”的不匹配:值“MTd_StaticDebug”与“MDd_DynamicDebug”不匹配。
现在有几个问题涉及如何解决这个问题:

但通常的答案是,将您的库更改为与其他库的构建类型匹配。问题是,我不想这样做,我想要一个DLL。并且我想像他们的文档中描述的那样静态链接google protobuf。我该如何实现这一点?

4个回答

8
正如@MSalters所指出的那样,在这里的答案中,代码生成的配置并没有指示构建的库类型,而是使用了c++ std lib的类型。为了在命令行构建上进行修改,需要使用-Dprotobuf_MSVC_STATIC_RUNTIME开关(对此参数的建议来自@Ation的答案here)。为了设置生成的makefiles从CMAKE中使用多线程DLL (/MD)特别是为了Google protobuf,您必须按照以下步骤进行调试:
cmake -G "NMake Makefiles" ^
-DCMAKE_BUILD_TYPE=Debug  -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ^
-DCMAKE_INSTALL_PREFIX=../../../install/debug ^
../..

或者发布:

cmake -G "NMake Makefiles" ^
-DCMAKE_BUILD_TYPE=Release -Dprotobuf_MSVC_STATIC_RUNTIME=OFF ^
-DCMAKE_INSTALL_PREFIX=../../../install/release ^
../..

以下nmake命令生成的代码将具有多线程DLL(/MD)类型的代码生成。
有关更多信息,请参见protobuf/README.md

1
对于那些不知道的人,你可以在这里找到在Windows上构建protobuf的步骤:https://github.com/protocolbuffers/protobuf/blob/master/cmake/README.md。 - Hossein
@Hossein:非常好的链接,谢谢。我不知道为什么它这么难找。我很荣幸将其包含在上面的答案中。 - Eric Duminil

4
你需要自己构建protobuf:
  • 确保你已经安装了CMake
  • protobuf github下载你所需版本的源代码
  • 在VS开发者命令行中打开该文件夹
  • 运行cmake

    cmake -G "Visual Studio 14" -Dprotobuf_MSVC_STATIC_RUNTIME=ON

你可能需要更改VS版本,请查看cmake帮助消息以获取正确的生成器名称。

之后,一切都应该很容易。打开生成的解决方案,在运行时库设置上进行检查,构建发布和调试版本。

然后将这些文件(或目录)包含到你的项目链接设置中(发布和调试应该有不同的lib文件)。


所以我开始朝那个方向前进。如果可能的话,我希望能够从命令行完成这个操作。 - Fantastic Mr Fox
devenv protobuf.sln /build [Release|Debug] /project protoc - Ation
请记住,默认情况下生成win32(x86)项目。如果您需要x64,请将“Win64”添加到生成器(Visual Studio 14 Win64)。 - Ation
我根据您关于参数protobuf_MSVC_STATIC_RUNTIME的建议,找到了命令行的答案。您能告诉我在哪里找到这方面的信息吗?我很想知道。 - Fantastic Mr Fox
从CMakeLists.txt本身开始:(。 - Ation

2

如果您静态构建它,则使用Visual Studio中的多线程(/MT)代码生成类型

不,你的错误就在这里。

/MT定义了您所使用的CRT库,而不是您所生成的库的类型开关。


好的,进展不错,我能否通过命令行设置这个参数? - Fantastic Mr Fox
@FantasticMrFox:哪个参数?显然/MT等是命令行参数。 - MSalters
因此,为了设置代码生成类型,必须在生成makefile期间完成。幸运的是,谷歌想到了这一点,并添加了protobuf_MSVC_STATIC_RUNTIME开关。我在我的答案中详细说明了这一点。 - Fantastic Mr Fox

-1
创建一个自定义的静态构建protobuf库,使用正确的库(您可能希望保留默认配置,以便在发布版本的DLL中使用)。这样,您的DLL将在调试版本中使用调试protobuf库,在发布版本中使用发布protobuf库。

1
这太模糊了。什么是“正确”的库?你能详细解释一下吗? - Fantastic Mr Fox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接