sndfile.h中的sf_count_t类型在libsndfile中是如何定义的?

How is the type sf_count_t in sndfile.h defined in libsndfile?

我正在尝试使用 Nyquist(一个音乐编程平台,参见:https://www.cs.cmu.edu/~music/nyquist/ or https://www.audacityteam.org/about/nyquist/) as a standalone program and it utilizes libsndfile (a library for reading and writing sound, see: http://www.mega-nerd.com/libsndfile/)。我正在 i686 GNU/Linux 机器 (Gentoo) 上执行此操作。

成功设置并无错误启动程序后,我尝试通过示例之一“(play (osc 60))”生成声音,但遇到此错误:

*** Fatal error : sizeof (off_t) != sizeof (sf_count_t)
*** This means that libsndfile was not configured correctly.

进一步调查(并向作者发送电子邮件)证明有些帮助,但解决方案离我的掌握还很远。作者建议查看 /usr/include/sndfile.h 以查看 sf_count_t 是如何定义的,并且(这部分)我的文件与他的相同:

/* The following typedef is system specific and is defined when libsndfile is
** compiled. sf_count_t will be a 64 bit value when the underlying OS allows
** 64 bit file offsets.
** On windows, we need to allow the same header file to be compiler by both GCC
** and the Microsoft compiler.
*/

#if (defined (_MSCVER) || defined (_MSC_VER))
typedef __int64         sf_count_t ;
#define SF_COUNT_MAX          0x7fffffffffffffffi64
#else
typedef int64_t sf_count_t ;
#define SF_COUNT_MAX            0x7FFFFFFFFFFFFFFFLL
#endif

作者在上面指出没有“32 位偏移量”选项。我不确定我将如何进行。这是 Nyquist 的作者推荐我调查的特定文件:https://github.com/erikd/libsndfile/blob/master/src/sndfile.h.in , and here is the entire source tree: https://github.com/erikd/libsndfile

以下是作者电子邮件回复中的一些相关片段:

"I'm guessing sf_count_t must be showing up as 32-bit and you want libsndfile to use 64-bit file offsets. I use nyquist/nylsf which is a local copy of libsndfile sources -- it's more work keeping them up to date (and so they probably aren't) but it's a lot easier to build and test when you have a consistent library."

"I use CMake and nyquist/CMakeLists.txt to build nyquist."

"It may be that one 32-bit machines, the default sf_count_t is 32 bits, but I don't think Nyquist supports this option."

这里是 Nyquist 的源代码:http://svn.code.sf.net/p/nyquist/code/trunk/nyquist/

这个问题对我来说很难解决,因为它是由相对晦涩的软件的小众用例组成的。这也使得该问题的支持前景有点令人担忧。我知道一点 C++,但我对自己解决这个问题的能力远没有信心。感谢阅读,祝大家节日快乐。如果您有任何建议,即使是在格式或编辑方面,请不要犹豫!

如果您查看 nyquist 中捆绑的 libsndfile 的来源,即 nylsf,那么您会看到 sndfile.h 是直接提供的。它将 sf_count_t 定义为 64 位整数。

libsndfile 来源没有这个文件,而是有一个 sndfile.h.in。这是 autoconf 的输入文件,它是一个工具,可以从此模板生成正确的 header 文件。它目前对 linux 系统的 sf_count_t 有以下定义(并且有一段时间了):

typedef @TYPEOF_SF_COUNT_T@ sf_count_t ;

@TYPEOF_SF_COUNT_T@ 将被 autoconf 替换,以生成一个 header,其工作类型为 sf_count_t,用于将要为其构建的系统。因此nyquist提供的header文件已经配置好了(估计是作者的系统)。

off_t是POSIX标准规定的类型,定义在系统的libc中。如果系统是 32 位,它在使用 GNU C 库的系统上的大小是 32 位。

这会导致相关完整性检查失败,因为 sf_count_toff_t 的大小不匹配。错误消息也是正确的,因为我们正在为构建使用不合适的配置 sndfile.h

据我所知,您有以下选择:

  1. nyquist 作者提供未配置的 sndfile.h.in 并在构建时使用 autoconf 配置此文件。

  2. 不要使用捆绑的 libsndfile 和 link 来对抗系统的。 (这需要一些知识和工作来更改构建脚本和 header 文件,可能还有其他意外问题)

  3. 如果您使用的是 GNU C 库 (glibc):预处理器宏 _FILE_OFFSET_BITS 可以设置为 64 以强制 off_t 的大小并且即使在 32 位系统上,文件接口的其余部分也可以使用 64 位版本。

    这可能有效,也可能无效,具体取决于您的系统是否支持它,并且它不是一个干净的解决方案,因为 libsndfile 的其他配置错误可能会被忽视。此标志还可能引入代码所依赖的其他接口更改,从而导致进一步构建或运行时 errors/vulnerabilities.

    尽管如此,我认为 cmake 的语法是添加:

    add_compile_definitions(_FILE_OFFSET_BITS=64)
    

    或取决于 cmake 版本:

    add_definitions(-D_FILE_OFFSET_BITS=64)
    

    在合适的CMakeLists.txt.

  4. 实际上 README in nyquist/nylsf 解释了它的文件是如何生成的。您可以尝试获取它所基于的相同 libsndfile 版本的源代码,并重复给出的步骤以生成为您的系统配置的 nylsf。它可能比 2. 和 3. 引起的问题更少,因为不会引入任何 version/interface 更改。