-
-
Notifications
You must be signed in to change notification settings - Fork 56.5k
Windows 64 bits issue with C API #15990
Description
System information (version)
- OpenCV => 3.4.4 and later
- Operating System / Platform => Windows 64 bits
- Compiler => Visual Studio 2017
Detailed description
Starting with rev. 8a3c394 C structure constructors are disabled when building OpenCV but enabled when building a program that uses OpenCV. Relevant part of the diff is:
--- a/modules/core/include/opencv2/core/types_c.h
+++ b/modules/core/include/opencv2/core/types_c.h
@@ -44,9 +44,7 @@
#ifndef OPENCV_CORE_TYPES_H
#define OPENCV_CORE_TYPES_H
-#if !defined(__OPENCV_BUILD) && !defined(CV__DISABLE_C_API_CTORS)
#define CV__ENABLE_C_API_CTORS // enable C API ctors (must be removed)
-#endif
This leads to an interesting problem when using, for instance, cvGetSize. According to https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention?view=vs-2017 when a function returns a struct with a size less than 64 bits:
- If it's a POD, it is returned in RAX
- If not, the caller creates a temporary and passes a reference to it in RCX; function arguments are shifted
So here, when building OpenCV, CvSize is a POD, so the function assumes RCX contains the pointer to the CvArr argument. But when using the function, CvSize is not a POD any more, and the caller puts a reference to a temporary CvSize in RCX and the argument in RDX... As you can imagine, this doesn't work very well.
The workaround is obviously to define CV__DISABLE_C_API_CTORS when building my own code, but such a runtime failure with no warning is a bit disheartening.
Steps to reproduce
Use cvGetSize on an IplImage in a 64 bits Windows program. This leads to a "Bad argument (Array should be CvMat or IplImage)", unless by change your temporary CvSize has the right magic value packed in...