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

时间:2016-01-28 05:02:21

标签: c++ qt bass

我正在尝试在可执行文件中播放.mod音频文件。我正在使用第三方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文件的绝对路径更改为相对路径(&#34; music.mod&#34;)时,文件无法播放。这是为什么?我将.mod文件放在与可执行文件相同的目录中以及包含.pro文件的目录中 - 这似乎不是问题。

另外,也许我错过了与如何在C ++中打开文件相关的内容。看起来MusicLoad函数需要第二个参数属于void*类型。我确信在这里我可以做得更好。理想情况下,我希望能够file存储.mod文件的相对路径并让它以这种方式播放,这样我就不必硬编码绝对路径。在一个完美的世界中,我想向file提供我的resources.qrc中.mod文件的路径,但是我必须使用QFile,我相信,这会赢得&#39;工作,因为我需要类型无效*。

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

编辑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();

...返回:

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

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

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

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

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

感谢大家的帮助!

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

2 个答案:

答案 0 :(得分:4)

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

In Qt Creator the default initial working directory is the directory that the .pro file is in, not the directory that the .exe ends up in.

Either put your file in that directory (the one that probably has all the source files and such in it as well, if you used the typical setup), or change the startup directory to the directory the .exe file is in (in the Run Settings area).

Although, based on your new comment below, I guess the problem is deeper than that... I can't really tell you why BASS doesn't like relative filenames but you can convert a relative path to an absolute one before passing it to BASS. There's a lot of ways to do that; using Qt's API you could:

#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

You won't be able to do that because loading resources from .qrc files is a Qt thing and BASS presumably does not use Qt internally (just like e.g. you could not open a resource with fopen), and doesn't understand how to load resources embedded by Qt. I am not familiar with BASS but a cursory glance at this documentation表明它还能够从内存缓冲区中播放数据。因此,一种方法是使用Qt将资源加载到可访问的内存中,然后传递该缓冲区。

答案 1 :(得分:-1)

  

在一个完美的世界中,我想在我的resources.qrc中提供带有.mod文件路径的文件,但是我必须使用QFile,我相信,这不会起作用,因为我需要这种类型无效*。

为什么你只相信?阅读Qt Doc。它会工作。不要使用课程QFile,而是使用QFileInfo

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