C++/QtでlibVLCライブラリを設定する際に直面したいくつかの問題

## issue1:exited with code -1073741515

### Background

- libvlcのlibおよびincludeディレクトリをプロジェクトディレクトリにコピーし、プロジェクトの.proファイルを修正した後、ビルドは成功しましたが、実行時にエラーが発生しました。

### Root Cause

- エラーコード-1073741515は、通常、Windowsのシステムエラー0xC0000135に対応しており、これは一般的な「DLLが見つからない」または「依存関係が欠如している」問題です。このエラーは、プログラムが実行中に必要な動的リンクライブラリ（DLL）を見つけられないことを示しています。

### Solution

libvlcの`sdk/lib`および`sdk/include`ディレクトリをコピーするだけでなく、次のファイルもlibvlcディレクトリからコピーする必要があります：

- `plugins`
- `axvlc.dll`
- `libvlc.dll`
- `libvlccore.dll`
- `npvlc.dll`


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3916068/3a03dd98-397b-47ee-9055-67a383a29015.png)

## issue2: Failed to create VLC media for file



### background 

```c++
   // Create a new libVLC media object
    media = libvlc_media_new_path(vlcInstance, filePath.toStdString().c_str());
    if (!media) {
        std::cerr << "Failed to create VLC media for file: " << filePath.toStdString() << std::endl;
        return;
    }
```



```
Failed to create VLC media for file: D:/Project/cppProject/ListenUp/testvideos/test.mp4
```



### rootcause



- Windowsではパス区切り文字は\であり、/ではありません。
- 非ASCII文字（例えば、中国語の文字）を含むファイルパスは、いくつかのlibVLC APIでは正しく処理されない場合があります。libVLCはCスタイルの文字列（char*）を使用しており、Unicodeのサポートが限られているため、ファイルパスはUTF-8エンコーディングに変換する必要があります。





### solution

```c++
QString normalizedPath = QDir::toNativeSeparators(filePath);
QByteArray filePathUtf8 = normalizedPath.toUtf8();
media = libvlc_media_new_path(vlcInstance, filePathUtf8.constData());

```



## Project Code

- mainwindow.cpp

```C++
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QPushButton>

#include <iostream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    // Initialize the central widget and layout
    QWidget *centralWidget = new QWidget(this); // Create the central widget
    setCentralWidget(centralWidget);           // Set it as the central widget of MainWindow

    videoWidget = new QWidget(this);           // Video playback widget
    layout = new QVBoxLayout();                // Layout
    layout->addWidget(videoWidget);            // Add the video widget to the layout

    // Add a button for opening video files
    QPushButton *openButton = new QPushButton("Open Video", this); // Create button
    layout->addWidget(openButton);                                // Add the button to the layout

    centralWidget->setLayout(layout);          // Apply the layout to the central widget

    // Connect the button's clicked signal to the slot
    connect(openButton, &QPushButton::clicked, this, &MainWindow::on_openButton_clicked);

    // Initialize libVLC
    const char *vlcArgs[] = { "--no-xlib" }; // Example: disable X11 if unnecessary
    vlcInstance = libvlc_new(1, vlcArgs);
    if (!vlcInstance) {
        std::cerr << "Failed to create VLC instance!" << std::endl;
    }
}

MainWindow::~MainWindow()
{
    // Cleanup libVLC resources
    if (mediaPlayer) {
        libvlc_media_player_stop(mediaPlayer);
        libvlc_media_player_release(mediaPlayer);
    }

    if (media) {
        libvlc_media_release(media);
    }

    if (vlcInstance) {
        libvlc_release(vlcInstance);
    }

    delete ui;
}

void MainWindow::on_openButton_clicked()
{
    // Open a file dialog to select a video file
    QString fileName = QFileDialog::getOpenFileName(this, "Open Video File", "", "Video Files (*.mp4 *.avi *.mkv *.flv)");
    if (!fileName.isEmpty()) {
        std::cout << "DEBUG FILE Found!" << std::endl;
        openVideo(fileName); // Call openVideo to open the video file
    }
}

void MainWindow::openVideo(const QString &filePath)
{
    if (!vlcInstance) {
        std::cerr << "VLC instance is not initialized!" << std::endl;
        return;
    }

    // Stop the current media if already playing
    if (mediaPlayer) {
        libvlc_media_player_stop(mediaPlayer);
        libvlc_media_player_release(mediaPlayer);
        mediaPlayer = nullptr;
    }

    if (media) {
        libvlc_media_release(media);
        media = nullptr;
    }

    // Convert file path to UTF-8
    QString normalizedPath = QDir::toNativeSeparators(filePath);
    QByteArray filePathUtf8 = normalizedPath.toUtf8();

    // Create a new libVLC media object
    media = libvlc_media_new_path(vlcInstance, filePathUtf8.constData());
    if (!media) {
        std::cerr << "Failed to create VLC media for file: " << filePath.toStdString() << std::endl;
        return;
    }

    // Create a new media player
    mediaPlayer = libvlc_media_player_new_from_media(media);
    if (!mediaPlayer) {
        std::cerr << "Failed to create VLC media player!" << std::endl;
        libvlc_media_release(media);
        media = nullptr;
        return;
    }

    // Set the video output widget for the media player
    libvlc_media_player_set_hwnd(mediaPlayer, reinterpret_cast<void *>(videoWidget->winId()));

    // Start playback
    if (libvlc_media_player_play(mediaPlayer) != 0) {
        std::cerr << "Failed to play the video!" << std::endl;
    } else {
        std::cout << "Playing video: " << filePath.toStdString() << std::endl;
    }
}
```
- mainwindow.h

```C++
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QFileDialog>
#include <QWidget>
#include <QVBoxLayout>
#include <vlc/vlc.h>
#include <vlc/libvlc.h>


namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_openButton_clicked();

private:
    Ui::MainWindow *ui;
    void openVideo(const QString &filePath); // Declaration of openVideo function

    // libVLC player-related members
    libvlc_instance_t *vlcInstance = nullptr;
    libvlc_media_player_t *mediaPlayer = nullptr;
    libvlc_media_t *media = nullptr;
    QWidget *videoWidget = nullptr;
    QVBoxLayout *layout = nullptr;
};

#endif // MAINWINDOW_H

```