使用已在另一个已使用的库中定义的函数名的库

时间:2016-01-13 12:13:53

标签: c++ visual-studio qt opencv compiler-errors

我正在用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中

但它会在所有项目中产生错误。

如何解决此问题?

4 个答案:

答案 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。您将确保编译代码时不会发生任何冲突。