gpt4 book ai didi

c++ - 从 Swift 访问 C++ 枚举

转载 作者:搜寻专家 更新时间:2023-10-31 22:41:34 24 4
gpt4 key购买 nike

我正在尝试从 Swift 访问用 C++ header 编写的 enum 值。具体来说,我在 OpenCV 的 hpp 头文件中有这个 enum,我想将它的值公开给 Swift。我试图在 Swift 和 Objective-C 之间设置一个桥接 header ,并在我想公开的 C++ 枚举值周围放置一个包装器,但编译器对此并不满意:

imgproc.hpp:C++头文件

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

如果我将这个枚举声明和 C++ 代码 (OpenCV) 导入到 OpenCVWrapper.mm 中,那么编译器就可以了,我也可以很好地使用它,但我想公开这个枚举到 Swift,所以它必须在头文件中。但是,当我直接在 Objective-C header 中公开 C++ 枚举时,有些地方不对。

是否有可能直接从 Objective-C header 访问 C++ 常量/枚举,以这种方式连接到 Swift?

我看过使用 extern,如 thisthis但在我的设置中仍然无法识别 C++ 常量。

最佳答案

OpenCV C++ 库中定义的 enum 值旨在与同一库中定义的 API 一起使用,并且需要包装这些 API 以便在 Swift 中使用。包装层还可以包含用于在 C++ 和 Swift 中的 enum 之间进行转换的代码,这样改变 C++ enum 的值就不会破坏 Swift 代码。这是可能的,因为包装器知道 Swift 和 C++ enum 值。

假设 C++ 头文件,称它为 CPP.h,有:

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++ - 从 Swift 访问 C++ 枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45451272/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com