C++ 访问C++;从Swift枚举

C++ 访问C++;从Swift枚举,c++,objective-c,swift,enums,bridging-header,C++,Objective C,Swift,Enums,Bridging Header,我试图访问SWIFT中的C++代码头中的枚举的值。具体地说,我在OpenCV的hpp头文件中有一个enum,我想向Swift公开它的值。我尝试在SWIFT和ObjuleC之间建立一个桥接头,并在一个C++的枚举值周围放置一个包装,我想公开它,但编译器对此并不满意: imgPRO.HPP :C++头文件< /P> enum ThresholdTypes { THRESH_BINARY = 0, THRESH_BINARY_INV = 1, THRESH_TRUN

我试图访问SWIFT中的C++代码头中的<代码>枚举<代码>的值。具体地说,我在OpenCV的hpp头文件中有一个
enum
,我想向Swift公开它的值。我尝试在SWIFT和ObjuleC之间建立一个桥接头,并在一个C++的枚举值周围放置一个包装,我想公开它,但编译器对此并不满意:

<强> imgPRO.HPP :C++头文件< /P>

enum ThresholdTypes {
    THRESH_BINARY     = 0,
    THRESH_BINARY_INV = 1,
    THRESH_TRUNC      = 2, 
    ...
};
桥接标头

#import "OpenCVWrapper.h"
OpenCVWrapper.h:我的Objective-C包装类将公开给Swift

#ifdef __cplusplus
#import <opencv2/core.hpp>
#import <opencv2/imgproc.hpp>
#endif

#import <Foundation/Foundation.h>

@interface OpenCVWrapper : NSObject

typedef enum {
    Binary = cv::THRESH_BINARY,  // ERROR: use of undeclared identifier `cv`
    BinaryInv = cv::THRESH_BINARY_INV  // ERROR: use of undeclared identifier `cv`
} ThresholdingType;

...    

@end
\ifdef\uuucplusplus
#进口
#进口
#恩迪夫
#进口
@接口OpenCVWrapper:NSObject
类型定义枚举{
Binary=cv::THRESH_Binary,//错误:使用了未声明的标识符`cv`
BinaryInv=cv::THRESH\u BINARY\u INV//错误:使用未声明的标识符`cv`
}阈值类型;
...    
@结束

如果我将这个EnUM声明和C++代码(OpenCV)导入到 OpenCVWrPlas.mm ,编译器就可以了,我也可以用它,但是我想把这个枚举暴露在SWIFT中,所以它必须在头文件中。但是,当我直接在ObjuleC C标题中公开C++枚举时,有些东西是不对的。

可以从Objut-C头直接访问C++常量/枚举,这样可以桥为SWIFT?< /P>


我已经查看了使用ExtLeNo,但是在我的设置中仍然没有识别C++常数。

< P>你唯一能做的就是在.h文件中创建一个全新的独立的枚举,它与C++枚举具有相同的数值,然后在Objy-C++文件中使用编译时断言(StasyAsStRT)。检查值是否相同

typedef enum {
    Binary = 7,  // cv::THRESH_BINARY: use of undeclared identifier `cv`
    BinaryInv = 12  // cv::THRESH_BINARY_INV: use of undeclared identifier `cv`
} ThresholdingType;

很明显,不管数字是多少,都是正确的。并检查.mm文件,以防原C++头发生更改。

> P>在OpenCV C++库中定义的 EnUM<代码>值,用于同一个库中定义的API,这些API需要被包装在SWIFT中使用。包装层还可以包括在C++中的代码> > EnUM < /C> > S和SWIFT之间的转换代码,这样改变C++银行代码> EnUM <代码> s不会破坏SWIFT代码。这是可能的,因为包装器既知道Swift也有C++(代码< EnUM<代码>值> ./P>

让我们说C++头文件,叫它“代码> CPP.H./Cube >,有:

namespace cv {
    enum ThresholdTypes { 
        THRESH_BINARY     = 0,
        THRESH_BINARY_INV = 111,
        THRESH_TRUNC      = 222
    };

    void useThreshold(ThresholdTypes t);
    ThresholdTypes returnThreshold();
};
执行对我们的目的并不重要。在
CPPWrapper.h
中,向Swift公开的包装器API看起来像

typedef enum {
    THRESH_BINARY,
    THRESH_BINARY_INV,
    THRESH_TRUNC,
    THRESH_UNKNOWN
} ThresholdTypesWrapper;

@interface CPPWrapper : NSObject

// The wrapper API operates in terms of wrapper `enum` values only.
// Translation between these and C++ `enum`s happens in the wrapper
// implementation.
+(void)useThreshold: (ThresholdTypesWrapper)thresholdType;
+(ThresholdTypesWrapper)returnThreshold;

@end
下面是包装器实现,
CPPWrapper.mm

cv::ThresholdTypes thresholdWrapped2Native(ThresholdTypesWrapper t) {
    if (t==THRESH_BINARY) return cv::THRESH_BINARY;
    else if (t==THRESH_BINARY_INV) return cv::THRESH_BINARY_INV;
    else if (t==THRESH_TRUNC) return cv::THRESH_TRUNC;
    // This should be very unlikely.
    else throw std::runtime_error("Unknown threshold value detected.");
}

ThresholdTypesWrapper thresholdNative2Wrapped(cv::ThresholdTypes t) {
    if (t==cv::THRESH_BINARY) return THRESH_BINARY;
    else if (t==cv::THRESH_BINARY_INV) return THRESH_BINARY_INV;
    else if (t==cv::THRESH_TRUNC) return THRESH_TRUNC;
    // We could throw instead, but returning unknown is more forgiving if
    // a new C++ enum value is added.
    else return THRESH_UNKNOWN;
}

@implementation CPPWrapper

+(void)useThreshold: (ThresholdTypesWrapper)thresholdType {
    cv::useThreshold(thresholdWrapped2Native(thresholdType));
}

+(ThresholdTypesWrapper)returnThreshold {
    return thresholdNative2Wrapped(cv::returnThreshold());
}

@end

上面的代码片段不是完整的源代码文件,但应该可以让您了解发生了什么。C++可以通过多种方式变得更健壮,但这超出了简短的答案范围。直接或间接地通过另一个.h文件包含.hpp文件并不重要。从C到Swift是否更容易桥接?在OpenCV 2中,有一个。不幸的是,OpenCV 3中似乎已经放弃了维护。这是2013年的问答。在谷歌上搜索“opencv c api”,我发现了一些c api文档。OpenCV 3的各个类的页面。@Scheff,我希望避免将来可能停止工作的解决方案,但感谢您的参考。这就是我寻求解决方案的原因:避免硬编码值。如果C++代码后来改变了值定义,银行代码会因为这一点而中断。这基本上是我在问了几天之后所做的事情。无论如何,谢谢你。我已经给出了你的答案,但仍将保留这个问题,以便将来可能采取更为精简的方法。@HuaTham:你找到解决问题的方法了吗?我也在为同样的事情挣扎。上面提到的答案不起作用。你能提供你的解决方案吗,这很好?我正在使用Swift4.2