将 OpenCV 集成到本机 macOS 应用程序中会导致链接器错误

问题描述 投票:0回答:1

我尝试将

OpenCV
native macOS app
集成在
Swift
中,结果是一堆
linker errors
。我有一个
M1 Mac
,下面是我尝试过的两种方法。

第一种方法:

首先,我做了

brew install opencv
,我使用
macOS
创建了一个原生
swift
应用程序,并使用
Xcode
,我转到 Finder 中的
/usr/local/Cellar/opencv
,并将所有 opencv 库拖放到 FrameWorks、Libraries 和 Embedded Content 中应用程序来自
opencv
的lib文件夹。

enter image description here

enter image description here

然后在

Build Settings
-> 我搜索了
Header Search Path
并添加了
/usr/local/Cellar/opencv/4.9.0_8/include/opencv4
并将其保留为
recursive

然后创建

OpenCVWrapper.h

#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>

NS_ASSUME_NONNULL_BEGIN

@interface OpenCVWrapper : NSObject

+ (NSImage *)convertToGrayscale:(NSImage *)image;

@end

NS_ASSUME_NONNULL_END

然后创建

OpenCVWrapper.mm

#import <opencv2/opencv.hpp>
#import <opencv2/imgcodecs/macosx.h>
#import "OpenCVWrapper.h"

@implementation OpenCVWrapper

+ (NSImage *)convertToGrayscale:(NSImage *)image {
    // Convert NSImage to cv::Mat
    cv::Mat cvImage = [self cvMatFromNSImage:image];

    // Convert to grayscale
    cv::Mat grayImage;
    cv::cvtColor(cvImage, grayImage, cv::COLOR_BGR2GRAY);

    // Convert cv::Mat back to NSImage
    NSImage *grayNSImage = [self nsImageFromCvMat:grayImage];
    return grayNSImage;
}

// Helper function to convert NSImage to cv::Mat
+ (cv::Mat)cvMatFromNSImage:(NSImage *)image {
    CGImageRef imageRef = [image CGImageForProposedRect:NULL context:NULL hints:nil];
    NSBitmapImageRep *bitmapRep = [[NSBitmapImageRep alloc] initWithCGImage:imageRef];

    cv::Mat mat((int)bitmapRep.pixelsHigh, (int)bitmapRep.pixelsWide, CV_8UC4, (void *)bitmapRep.bitmapData, (int)bitmapRep.bytesPerRow);
    cv::Mat matBGR;
    cv::cvtColor(mat, matBGR, cv::COLOR_RGBA2BGR);
    return matBGR;
}

// Helper function to convert cv::Mat to NSImage
+ (NSImage *)nsImageFromCvMat:(const cv::Mat&)cvMat {
    NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize() * cvMat.total()];
    CGColorSpaceRef colorSpace;
    if (cvMat.type() == CV_8UC1) {
        colorSpace = CGColorSpaceCreateDeviceGray();
    } else {
        colorSpace = CGColorSpaceCreateDeviceRGB();
    }

    CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
    CGImageRef imageRef = CGImageCreate(cvMat.cols,                                   // width
                                        cvMat.rows,                                   // height
                                        8,                                            // bits per component
                                        8 * cvMat.elemSize(),                         // bits per pixel
                                        cvMat.step.p[0],                              // bytesPerRow
                                        colorSpace,                                   // colorspace
                                        kCGImageAlphaNone | kCGBitmapByteOrderDefault,// bitmap info
                                        provider,                                     // CGDataProviderRef
                                        NULL,                                         // decode
                                        false,                                        // should interpolate
                                        kCGRenderingIntentDefault                     // intent
                                        );
    NSImage *image = [[NSImage alloc] initWithCGImage:imageRef size:NSMakeSize(cvMat.cols, cvMat.rows)];

    CGImageRelease(imageRef);
    CGDataProviderRelease(provider);
    CGColorSpaceRelease(colorSpace);

    return image;
}

@end

然后我创建了

PrefixHeader.pch

#ifndef PrefixHeader_pch
#define PrefixHeader_pch

#ifdef __cplusplus
#include <opencv2/opencv.hpp>
#endif

#endif

Bridging-Header
中我添加了
#import "OpenCVWrapper.h"

Build Settings
-> 我设置
Precompile Prefix Header
-> 是 &
PrefixHeader
->
$(SRCROOT)/mymacosapp/PrefixHeader.pch

完成所有这些操作后,我收到错误消息

Undefined symbols for architecture arm64:
  "cv::Mat::Mat(int, int, int, void*, unsigned long)", referenced from:
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
  "cv::Mat::Mat()", referenced from:
      +[OpenCVWrapper convertToGrayscale:] in OpenCVWrapper.o
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
  "cv::Mat::~Mat()", referenced from:
      +[OpenCVWrapper convertToGrayscale:] in OpenCVWrapper.o
      +[OpenCVWrapper convertToGrayscale:] in OpenCVWrapper.o
      +[OpenCVWrapper convertToGrayscale:] in OpenCVWrapper.o
      +[OpenCVWrapper convertToGrayscale:] in OpenCVWrapper.o
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
      ...
  "cv::cvtColor(cv::_InputArray const&, cv::_OutputArray const&, int, int)", referenced from:
      +[OpenCVWrapper convertToGrayscale:] in OpenCVWrapper.o
      +[OpenCVWrapper cvMatFromNSImage:] in OpenCVWrapper.o
  "cv::Mat::total() const", referenced from:
      +[OpenCVWrapper nsImageFromCvMat:] in OpenCVWrapper.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

第二种方式:

我创建了一个新的

native
macOS 项目。我刚刚复制了我在第一种方式中分享的
OpenCVWrapper.h
OpenCVWrapper.mm
Bridging Header
PrefixHeader.pch

我从

OpenCV
下载了
Github
源代码。然后我就跑了

python3 platforms/apple/build_xcframework.py --out build_all \
--macos_deployment_target 12.15 \
--macos_archs arm64 \
--build_only_specified_archs True \
--without objc

build_all
文件夹中,它创建了一个
opencv2.xcframework
,我将其拖到
Frameworks, Libraries and Embedded Content
Xcode

我收到错误消息

Undefined symbols for architecture arm64:
  "_clBuildProgram", referenced from:
      _clBuildProgram_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCompileProgram", referenced from:
      _clCompileProgram_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateBuffer", referenced from:
      _clCreateBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateCommandQueue", referenced from:
      _clCreateCommandQueue_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateContext", referenced from:
      _clCreateContext_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateContextFromType", referenced from:
      _clCreateContextFromType_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateImage", referenced from:
      _clCreateImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateImage2D", referenced from:
      _clCreateImage2D_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateImage3D", referenced from:
      _clCreateImage3D_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateKernel", referenced from:
      _clCreateKernel_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateKernelsInProgram", referenced from:
      _clCreateKernelsInProgram_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateProgramWithBinary", referenced from:
      _clCreateProgramWithBinary_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateProgramWithBuiltInKernels", referenced from:
      _clCreateProgramWithBuiltInKernels_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateProgramWithSource", referenced from:
      _clCreateProgramWithSource_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateSampler", referenced from:
      _clCreateSampler_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateSubBuffer", referenced from:
      _clCreateSubBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateSubDevices", referenced from:
      _clCreateSubDevices_pfn in opencv2[arm64][115](opencl_core.o)
  "_clCreateUserEvent", referenced from:
      _clCreateUserEvent_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueBarrier", referenced from:
      _clEnqueueBarrier_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueBarrierWithWaitList", referenced from:
      _clEnqueueBarrierWithWaitList_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueCopyBuffer", referenced from:
      _clEnqueueCopyBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueCopyBufferRect", referenced from:
      _clEnqueueCopyBufferRect_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueCopyBufferToImage", referenced from:
      _clEnqueueCopyBufferToImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueCopyImage", referenced from:
      _clEnqueueCopyImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueCopyImageToBuffer", referenced from:
      _clEnqueueCopyImageToBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueFillBuffer", referenced from:
      _clEnqueueFillBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueFillImage", referenced from:
      _clEnqueueFillImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueMapBuffer", referenced from:
      _clEnqueueMapBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueMapImage", referenced from:
      _clEnqueueMapImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueMarker", referenced from:
      _clEnqueueMarker_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueMarkerWithWaitList", referenced from:
      _clEnqueueMarkerWithWaitList_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueMigrateMemObjects", referenced from:
      _clEnqueueMigrateMemObjects_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueNDRangeKernel", referenced from:
      _clEnqueueNDRangeKernel_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueNativeKernel", referenced from:
      _clEnqueueNativeKernel_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueReadBuffer", referenced from:
      _clEnqueueReadBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueReadBufferRect", referenced from:
      _clEnqueueReadBufferRect_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueReadImage", referenced from:
      _clEnqueueReadImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueTask", referenced from:
      _clEnqueueTask_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueUnmapMemObject", referenced from:
      _clEnqueueUnmapMemObject_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueWaitForEvents", referenced from:
      _clEnqueueWaitForEvents_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueWriteBuffer", referenced from:
      _clEnqueueWriteBuffer_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueWriteBufferRect", referenced from:
      _clEnqueueWriteBufferRect_pfn in opencv2[arm64][115](opencl_core.o)
  "_clEnqueueWriteImage", referenced from:
      _clEnqueueWriteImage_pfn in opencv2[arm64][115](opencl_core.o)
  "_clFinish", referenced from:
      _clFinish_pfn in opencv2[arm64][115](opencl_core.o)
  "_clFlush", referenced from:
      _clFlush_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetCommandQueueInfo", referenced from:
      _clGetCommandQueueInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetContextInfo", referenced from:
      _clGetContextInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetDeviceIDs", referenced from:
      _clGetDeviceIDs_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetDeviceInfo", referenced from:
      _clGetDeviceInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetEventInfo", referenced from:
      _clGetEventInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetEventProfilingInfo", referenced from:
      _clGetEventProfilingInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetExtensionFunctionAddress", referenced from:
      _clGetExtensionFunctionAddress_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetExtensionFunctionAddressForPlatform", referenced from:
      _clGetExtensionFunctionAddressForPlatform_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetImageInfo", referenced from:
      _clGetImageInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetKernelArgInfo", referenced from:
      _clGetKernelArgInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetKernelInfo", referenced from:
      _clGetKernelInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetKernelWorkGroupInfo", referenced from:
      _clGetKernelWorkGroupInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetMemObjectInfo", referenced from:
      _clGetMemObjectInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetPlatformIDs", referenced from:
      _clGetPlatformIDs_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetPlatformInfo", referenced from:
      _clGetPlatformInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetProgramBuildInfo", referenced from:
      _clGetProgramBuildInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetProgramInfo", referenced from:
      _clGetProgramInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetSamplerInfo", referenced from:
      _clGetSamplerInfo_pfn in opencv2[arm64][115](opencl_core.o)
  "_clGetSupportedImageFormats", referenced from:
      _clGetSupportedImageFormats_pfn in opencv2[arm64][115](opencl_core.o)
  "_clLinkProgram", referenced from:
      _clLinkProgram_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseCommandQueue", referenced from:
      _clReleaseCommandQueue_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseContext", referenced from:
      _clReleaseContext_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseDevice", referenced from:
      _clReleaseDevice_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseEvent", referenced from:
      _clReleaseEvent_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseKernel", referenced from:
      _clReleaseKernel_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseMemObject", referenced from:
      _clReleaseMemObject_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseProgram", referenced from:
      _clReleaseProgram_pfn in opencv2[arm64][115](opencl_core.o)
  "_clReleaseSampler", referenced from:
      _clReleaseSampler_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainCommandQueue", referenced from:
      _clRetainCommandQueue_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainContext", referenced from:
      _clRetainContext_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainDevice", referenced from:
      _clRetainDevice_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainEvent", referenced from:
      _clRetainEvent_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainKernel", referenced from:
      _clRetainKernel_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainMemObject", referenced from:
      _clRetainMemObject_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainProgram", referenced from:
      _clRetainProgram_pfn in opencv2[arm64][115](opencl_core.o)
  "_clRetainSampler", referenced from:
      _clRetainSampler_pfn in opencv2[arm64][115](opencl_core.o)
  "_clSetEventCallback", referenced from:
      _clSetEventCallback_pfn in opencv2[arm64][115](opencl_core.o)
  "_clSetKernelArg", referenced from:
      _clSetKernelArg_pfn in opencv2[arm64][115](opencl_core.o)
  "_clSetMemObjectDestructorCallback", referenced from:
      _clSetMemObjectDestructorCallback_pfn in opencv2[arm64][115](opencl_core.o)
  "_clSetUserEventStatus", referenced from:
      _clSetUserEventStatus_pfn in opencv2[arm64][115](opencl_core.o)
  "_clUnloadCompiler", referenced from:
      _clUnloadCompiler_pfn in opencv2[arm64][115](opencl_core.o)
  "_clUnloadPlatformCompiler", referenced from:
      _clUnloadPlatformCompiler_pfn in opencv2[arm64][115](opencl_core.o)
  "_clWaitForEvents", referenced from:
      _clWaitForEvents_pfn in opencv2[arm64][115](opencl_core.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
c++ swift objective-c macos opencv
1个回答
0
投票

您的构建完全错误。您使用的脚本来自here,该目录仅包含用于与您的实际硬件不同的平台的cross-compilation的脚本。从您的 CLI 中,我假设您的构建尝试为 Linux 创建

arm64
交叉编译的二进制文件,但将它们打包到 MacOS 原生 X-Framework 发行档案中。

在这种情况下,强烈建议删除当前版本,然后通过自制程序安装

cmake
,像这样运行:

mkdir build && cd build
cmake -LAH ..

...并使用开发人员提示检查打印的变量。然后您可以设置所有内容并准备您的 XFramework 存档并正确扣除架构。

© www.soinside.com 2019 - 2024. All rights reserved.