C++ char* 相对文件路径? (Qt)

C++ char* relative file path? (Qt)

我正在尝试在可执行文件中播放 .mod 音频文件。我正在使用第 3 方 BASSMOD .dll。当我提供文件的完整路径时,我可以播放音频文件,但是当我提供相对路径时,我无法播放它。这里有一些片段。

main.cpp

#include <QCoreApplication>
#include "bassmod.h"

// define file location
const char* file = "C:/Users/Downloads/test4/console/music.mod";

void startMusic() {
  BASSMOD_Init(-1, 44100, 0);
  BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS);
  BASSMOD_MusicPlayEx(0,-1,TRUE);
}

int main(int argc, char *argv[])
{
  QCoreApplication a(argc, argv);
  startMusic();
  return a.exec();
}

bassmod.h(相关片段)

BOOL BASSDEF(BASSMOD_MusicLoad)(BOOL mem, void* file, DWORD offset, DWORD length, DWORD flags);

我关心的函数是BASSMOD_MusicLoad。就这个项目而言,.mod 文件播放没有问题。但是,当我尝试将 .mod 文件的绝对路径更改为相对路径 ("music.mod") 时,文件无法播放。这是为什么?我在与可执行文件相同的目录中以及包含 .pro 文件的目录中有 .mod 文件——这似乎不是问题所在。

此外,也许我遗漏了与 C++ 中文件打开方式相关的内容。看起来 MusicLoad 函数 要求 第二个参数的类型为 void*。我敢肯定有很多不同的事情我可以在这里做得更好。理想情况下,我希望能够让 file 存储 .mod 文件的相对路径并让它以这种方式播放,这样我就不必对绝对路径进行硬编码。在一个完美的世界中,我想在我的 resources.qrc 中提供 file 到 .mod 文件的路径,但我相信我必须使用 QFile ,这是行不通的,因为我需要类型为 void*.

非常感谢对初学者的任何帮助。


编辑 01: 谢谢大家的帮助!我让它工作(至少使用相对文件路径)。有两种方法可以做到这一点。这是我所做的以及我是如何测试它的:

第一种情况假设 BASSMOD(或您正在使用的任何外部 dll)不处理相对路径。

const char* file = "C:/debug/music.mod"; // same dir as .exe
QFileInfo info("music.mod");
QString path = info.absoluteFilePath();
const string& tmp = path.toStdString();
const char* raw = tmp.data();

这些是我设置的测试项目。当我 运行 BASSMOD_MusicLoad(FALSE,(void*)file,0,0,BASS_MUSIC_RAMPS); 时,它按预期工作。那是我硬编码完整绝对路径的时候。

当我运行BASSMOD_MusicLoad(FALSE,(void*)raw,0,0,BASS_MUSIC_RAMPS);时,它不起作用。所以我决定打印出所有东西的值,看看哪里出了问题:

 cout << "Qstring path: ";
 qDebug() << path;
 cout << "string& tmp: ";
 cout << tmp << endl;
 cout << "raw: ";
 cout << raw << endl;
 cout << "full char* file: ";
 cout << file;
 startMusic();

...returns 这个:

Qstring path:
"C:/myApp/build-Debug/music.mod"
string& tmp:
C:/myApp/build-Debug/music.mod
raw:
C:/myApp/build-Debug/music.mod
full char* file:
C:/myApp/build-Debug/debug/music.mod

注意区别了吗?当我对文件的完整路径进行硬编码时,我发现(感谢@F运行kOsterfeld 和@JasonC)当前工作目录实际上不在 .exe (/debug) 或 .pro 文件所在的位置位于。它实际上与 Makefile 在同一目录中。

所以我将其更改为:QFileInfo info("./debug/x.m"); 并且有效。

尽管问题最终是我不知道当前工作目录在哪里,@Radek、@SaZ 和@JasonC 的解决方案帮助找到了另一种方法来解决这个问题(另外它向我展示了如何获得工作目录和类型之间的转换)。对于那些想要使用 QFileInfo 来确定您在文件系统中的实际位置的人来说,这是一个很好的参考。如果我使用的 dll 不能很好地处理相对路径,我会使用这个解决方案。然而...

我想知道我是否可以将相同的解决方案应用于我的原始代码(不使用 QFileInfo 和转换类型等)。我假设 BASSMOD 没有开箱即用地处理相对路径。我错了。我将 file 变量更改为 const char* file = "./debug/x.m"; 它起作用了!

感谢大家的帮助!

但是,我仍然希望使用 Qt 资源文件中的 music.mod 来实现它。但是,根据回复,除非您使用的第 3 方库支持 Qt 资源系统,否则看起来不可能。

I have the .mod file in the same directory as the executable.

在 Qt Creator 中,默认初始工作目录是 .pro 文件所在的目录,而不是 .exe 最终所在的目录。

要么将您的文件放在该目录中(如果您使用的是典型设置,该目录中可能还包含所有源文件等),或者将启动目录更改为 .exe 文件所在的目录在(在 运行 设置区域)。

不过,根据你在下面的新评论,我想问题比这更深......我真的不能告诉你为什么 BASS 不喜欢相对文件名,但你可以将相对路径转换为绝对路径在将它传递给 BASS 之前。有很多方法可以做到这一点;使用 Qt 的 API 你可以:

#include <QFileInfo>

...
const char* file = "music.mod";  // Your relative path.
...

BASSMOD_MusicLoad(...,
                  (void*)QFileInfo(file).absoluteFilePath().toAscii().data(),
                  ...);

In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc

您将无法这样做,因为从 .qrc 文件加载资源是 Qt 的事情,BASS 可能不会在内部使用 Qt(就像您无法使用 fopen 打开资源一样) ,并且不了解如何加载 Qt 嵌入的资源。我对 BASS 不熟悉,但粗略地浏览 this documentation 表明它也有能力从 in-memory 缓冲区播放数据。因此,一种方法是使用 Qt 将资源加载到可访问的内存中,然后传递该缓冲区。

In a perfect world, I would like to supply file with a path to the .mod file in my resources.qrc, but then I would have to use QFile, I believe, which won't work because I need the type to be void*.

你为什么只相信?阅读 Qt 文档。它会起作用。不要使用 class QFileQFileInfo.

QFileInfo info(:/resourcePrefix/name);
QString path = info.absoluteFilePath();
void* rawPtr = (void*)path.toStdString().c_str();