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:
#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;
};
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
}
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.
The problem is DllImportAttribute
, particularly CharSet = CharSet.Unicode
.
To solve it just remove CharSet = CharSet.Unicode
[DllImport("ImageProviderAPI.dll")]