cv::VideoCapture 在 C# 项目中从 DLL 使用文件或流时不打开文件或流

cv::VideoCapture doesn't open a file or stream when using it from DLL in C# project

我通过 DllImports 在 C++ 中使用 Unity 的 C# 脚本和 OpenCV。我的目标是在来自 OpenCV 的 Unity 场景中创建一个视频流。 Unity 加载包含 OpenCV 函数的库。 问题是当从 dll(从 Unity)调用时 cv::VideoCapture().open("path_to_file_or_stream") 总是 return false。

当我将 C++ 代码构建为可执行文件时,一切正常。我正在使用 CMAKE 构建我的项目。

# Build exe
ADD_EXECUTABLE(${PROJECT_NAME} ${SRCS_DIR} ${INCL_DIR})

# Build lib
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS_DIR} ${INCL_DIR})

# OpenCV
FIND_PACKAGE(OpenCV)
IF(OpenCV_FOUND)
  TARGET_LINK_LIBRARIES(${PROJECT_NAME} PUBLIC ${OpenCV_LIBS})
    MESSAGE(STATUS "[OpenCV_LIBS] " ${OpenCV_LIBS})
ENDIF()

但是,当 运行 来自 dll 时,cv::VideoCapture() 未打开。

这是我目前的一些代码:

C++/ImageProviderAPI.h

#define IMAGE_API __declspec(dllexport)
extern "C"
{
    ...
    IMAGE_API ImageProviderAPI* InitProvider(const char* url);
    IMAGE_API void StartProvider(ImageProviderAPI* api);
    ...
}

class ImageProviderAPI {

public:

    ImageProviderAPI(std::string url);
    ~ImageProviderAPI();

    void start();

private:

    std::string m_url;
    cv::VideoCapture* p_videoCapture;
};

C++/ImageProviderAPI.h

IMAGE_API ImageProviderAPI* InitProvider(const char* url) {
    return new ImageProviderAPI(std::string(url));
}

IMAGE_API void StartProvider(ImageProviderAPI* api) {
    api->start();
}

ImageProviderAPI::ImageProviderAPI(std::string url) : 
m_url(url), p_videoCapture(nullptr) {

}

void ImageProviderAPI::start() {
    p_videoCapture = new cv::VideoCapture();
    bool res = p_videoCapture->open(m_url);     // m_url - path to file or stream url
                                                // Always false if called from dll 
    // or this way

    p_videoCapture = new cv::VideoCapture(m_url);
    bool res = p_videoCapture->isOpened();      // Always false if called from dll
}

C# / MyScript.cs

public class MyScript: MonoBehaviour {
    ...
    [DllImport("ImageProviderAPI.dll", CharSet = CharSet.Unicode)]
    private static extern IntPtr InitProvider(string url);

    [DllImport("ImageProviderAPI.dll", CharSet = CharSet.Unicode)]
    private static extern void StartProvider(IntPtr api);

    private IntPtr API;

    void Start() {
        API = InitProvider("path_to_file_or_stream_url");
        StartProvider(API);
    }

    void Update() {
        // Do stuff
    }
}

例如,其他一些 OpenCV 函数,如 cv::imreadcv::resizecv::cvtColor 在从 dll 调用时有效。我使用 std::ofstream 记录了 VideoCapture 打开结果。

没想到运行作为exe或dll会有什么区别。也许我在 dll import/export.

期间遗漏了一些东西

问题是 DllImportAttribute,尤其是 CharSet = CharSet.Unicode

要解决它只需删除 CharSet = CharSet.Unicode

[DllImport("ImageProviderAPI.dll")]