我正在用Qt和OpenCV 3.0开发一个C ++项目。当尝试使用OpenCV的人脸识别模块时,我收到错误。
访问文件predict_collector.hpp和下面的课程时
class CV_EXPORTS_W PredictCollector {
protected:
...
public:
...
CV_WRAP virtual bool emit(const int label, const double dist, const int state = 0);
};
编译器将emit关键字与其在Qt中的定义相关联,从而生成此错误:
\libs\opencv3.0.0\opencv_contrib-master\modules\face\include\opencv2\face/predict_collector.hpp(77): error C2059: syntax error: 'const'
因为'const'
是C ++中的关键字,不能将参数传递给Qt emit函数。您会看到编译器将emit视为Qt版本。
注意emit是一个宏函数,它不是普通函数,所以我们不能使用命名空间,你可以在qobjectsdef.h中看到:
#ifndef QT_NO_EMIT
# define emit
#endif
我试图制作
#undef emit
在文件predict_collector.hpp中但它会在所有项目中产生错误。
如何解决此问题?
答案 0 :(得分:2)
在代码中使用命名空间调用。这允许您编写namespace1::functionX()
和namespace2::functionX().
如果无法做到,请尝试添加
namespace namespace1{
//code here
}
或
using namespace
//Code here//
如果在您自己的代码中使用这些并没有修复错误,那么可以将其添加到相关的OpenCV和Qt文件中。
答案 1 :(得分:2)
请参阅:https://stackoverflow.com/a/22190519/355177
简而言之:
您可以定义QT_NO_KEYWORDS宏,禁用“信号”和“插槽”宏。
如果您使用QMake:
CONFIG + = no_keywords
如果您正在使用其他构建系统,请执行将-DQT_NO_KEYWORDS传递给编译器所需的任何内容。
如果要使用Qt“emit”,请使用Q_EMIT。
答案 2 :(得分:1)
这确实是定义宏的问题之一(尤其是没有前缀的宏,QT中的宏确实应该被定义为QT_EMIT或类似的以最小化冲突)。
您最有可能需要做的是在包含OpenCV之前取消定义宏,然后再定义它。并且在每个调用发射的地方都这样做。
命名空间在这里不太可能有用,因为宏"发出"仍将被定义,并仍将与函数名称冲突。
这样的事情:
<string>
并且在每个地方都会调用emit。如果在OpenCV标头之前包含所有QT标头,并且如果不在cpp中使用QT发射,则可以避免返回发回的需要。然后只需取消定义emit宏就可以了:
static bool HasFaildSessions()
{
int counter = 0;
bool result = false;
string connectionString = ConfigurationManager.ConnectionStrings["MySwipe"].ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand command = new SqlCommand("select TOP 3 [Resp_Code],JV_Date from dbo.log_jv_header order by JV_Date desc", connection))
{
using (SqlDataReader dataReader = command.ExecuteReader())
{
while (dataReader.Read())
{
if (string.Equals(dataReader.GetString(0), "01"))
counter++;
}
}
}
}
if (counter == 3)
result = true;
return result;
}
static void Main(string[] args)
{
While(true) //infinite loop
{
if (HasFaildSessions())
{
email_send();
Console.WriteLine("Email Send to Operations Department.");
Console.ReadLine();
}
Thread.Sleep(300000);
}
}
另一个选项(基于你的上一次编辑)可能是定义QT_NO_EMIT宏,以便在包含QT标题之前,QT不会定义emit,如:
#ifdef emit
// undef and store emit
#define MY_EMIT_STORE emit
#undef emit
#endif
#include "predict_collector.hpp"
#ifdef MY_EMIT_STORE
// return emit back for QT
#define emit MY_EMIT_STORE
#undef MY_EMIT_STORE
#endif
或者通常在编译器标志中定义QT_NO_EMIT(&#34; -DQT_NO_EMIT&#34;)。
答案 3 :(得分:1)
我在调用任何Qt包含文件之前放了#include <opencv2/face.hpp>
。这样就不会定义emit
关键字。
并且递归地,如果包含#include <opencv2/face.hpp>
的标题包含在项目的另一个头文件中,请小心将其放在任何Qt包含文件之前,并将其放在第二个文件中。
重要的是确保在调用Qt宏#include <opencv2/face.hpp>
的定义之前调用emit
。您将确保编译代码时不会发生任何冲突。