I'm using Unity's C# scripts and OpenCV in C++ via DllImports. My goal is to create an video stream inside Unity scene coming from OpenCV . Unity loads the library, which contains OpenCV functions. The problem is that cv::VideoCapture().open("path_to_file_or_stream") always return false when get called from dll (from Unity).
When I build my C++ code as executable everything works just perfect. I am using CMAKE to build my project.
# 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() However, when running from dll, cv::VideoCapture() is not opening.
Here is some code I have so far:
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 } } For example some other OpenCV functions like cv::imread, cv::resize, cv::cvtColor works when called from dll. I used std::ofstream to log VideoCapture opening result.
I didn't expect that there any difference when running as exe or dll. Maybe I missed something during dll import/export.
cv::VideoCapture. RemovingCharSet = CharSet.Unicodesolves the problem.