【问题标题】:Swift build error "Cannot find 'C++ byte array' in scope"Swift 构建错误“在范围内找不到‘C++ 字节数组’”
【发布时间】:2021-03-24 08:41:12
【问题描述】:

Xcode 构建无法识别 C++ .cpp 文件中定义的字节数组 sensor_data_bytes。

它确实可以识别在相同文件中定义的 char 变量,并且还可以识别无符号 sensor_data_bytes。

func peripheral() 接收它需要复制到 C++ char 数组 sensor_data_bytes 的 BLE 通知数据。

结构

我的工作区 Objective-C 应用项目“sim_backend_UI”导入两个静态库项目(A 和 B)。

A)“mobile_sensor_API”包含:

mobile_BLE_central.swift  
mobile_sensor_API.h  
mobile_sensor_API.mm  
mobile_sensor_API-Bridging-Header.h

B) 'mobile_hub' 包含:

sdp_BLE.hpp  
sdp.cpp 

代码

// sdp_BLE.hpp, C++ in ObjC mobile_hub project
    
#ifndef BLE_bridge_h
#define BLE_bridge_h
    
//  Hublib receive of antenna data from sensor BLE:
#define SENSOR_DATA_BYTES 300
extern int BLE_packet_ready;
extern int BLE_packet_overruns;
extern char sensor_data_buf[];
extern unsigned sensor_data_bytes;

#endif //BLE_bridge_h
// sdp.cpp in ObjC mobile_hub project

#include "sdp.hpp"
#include "sdp_BLE.hpp"
    
//  Controls for receive of antenna data from Swift BLE notification data:
int BLE_packet_ready = 0;
int BLE_packet_overruns = 0;
char sensor_data_buf[ SENSOR_DATA_BYTES ];
unsigned sensor_data_bytes = 0;
. . .
    
//  Copies the data from func peripheral(...didUpdateValueFor...) to pucBuf.
int sdpRead(SDP_Handle ftHandle, UCHAR *pucBuf, ULONG ulBufferSize, ULONG *pulBytesTransferred, DWORD dwTimeOutInMs = 1000)
{
    int rv = 0;
    // Await sensor antenna data packet:
    // Poll buffer ready flag:
    for(;;)
    {
        // Buffer flag?
        if( BLE_packet_ready > 0 )
        {
            // Copy from BLE buf to hublib buffer:
            memcpy( pucBuf, sensor_data_buf, sensor_data_bytes );
            *pulBytesTransferred = sensor_data_bytes;
            // Lower flag:
            BLE_packet_ready = 0;
            // return
            break;                        
        }
        std::this_thread::yield();
        continue;
    }
    return rv;
}
// mobile_sensor_API-Bridging-Header.h
//  Bridging header from ObjC project that contains C++ to same ObjC project's .swift
//  Use this file to import your target's public headers that you would like to expose to Swift.

//#import "sdp_BLE.hpp"
    #define SENSOR_DATA_BYTES 300
    extern int BLE_packet_ready ;
    extern int BLE_packet_overruns ;
    extern  char sensor_data_buf[];
    extern  unsigned sensor_data_bytes ;

// mobile_sensor_API.h
//  ObjC static lib project: mobile_sensor_API
//  Contains .mm and .swift files
    
#import <Foundation/Foundation.h>
    
@interface Mobile_Sensor_API : NSObject
    
//  Swift interface to data-plane within mobile_hub objC static lib project:
extern "C++"  int BLE_packet_ready;
extern "C++"  int BLE_packet_overruns;
extern "C++"  char sensor_data_buf[];
extern "C++"  unsigned sensor_data_bytes;
// mobile_BLE_central.swift
//   ObjC static lib project: mobile_sensor_API
        
import UIKit
import CoreBluetooth
import os
    
@objc open
class BLE_Central: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate
{
    . . .

    /* Antenna Data packet received from sensor
     * This callback lets us know more data has arrived via notification on the characteristic */
    public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) 
    {
        // Buf flag still up?
        if( BLE_packet_ready > 0 )
        {
            // Count overruns:
            BLE_packet_overruns += 1;
        }
        else // else, Buf flag down?
        {
            sensor_data_bytes = UInt32(characteristic.value!.count);
            let characteristicData = characteristic.value

// TODO: build error "Cannot find 'sensor_data_buf' in scope" here
            characteristicData.copyBytes( to: sensor_data_buf, count: sensor_data_bytes );
// 
            // Raise buffer flag:
            BLE_packet_ready = 1;
        }
    }

    . . .
}

【问题讨论】:

  • 是什么让你认为 Swift 参与其中?
  • 非常好心地编辑了一下,让你看到他的问题更明显。该错误正在迅速发生,但可能来自 c++,因为可能未定义 sensor_data_buf。 @Doug sensor_data_buf 是通过桥接头暴露的全局变量对吗?
  • 奥尔森:是的。在页面上搜索它的 C++ 定义、.h 接口以及 Swift 使用的位置。
  • 如果您将反对票视为社区责任,它不应该打扰您。从长远来看,其他人可能会投票。如果接口正确声明了全局,您应该检查mobile_sensor_API.h,通过测试您是否可以从 c++ 或 c、objc 或 objc++ 端访问它
  • OlSen:感谢您的编辑!我期待在早上实施 Answer(我在加利福尼亚)

标签: c++ objective-c swift xcode core-bluetooth


【解决方案1】:

确实存在范围问题。

您的 swift 模块不知道全局 char sensor_data_buf[300]。 我猜这是因为sdp_BLE.hpp 中的宏#ifndef BLE_bridge_h 阻止它在桥接头中完全公开。预处理器可能认为一切都很好,但宏阻止它正确暴露。

只是测试几天前如何在我们的 hub_lib 项目中声明它..

在桥接头中写一个明确的声明

// mobile_sensor_API-Bridging-Header.h
//  Bridging header from ObjC project that contains C++ to same ObjC project's .swift
//  Use this file to import your target's public headers that you would like to expose to Swift.

#import "sdp_BLE.hpp"

extern unsigned sensor_data_bytes;
extern char sensor_data_buf[300];

还有一个微小的变化,因为您在 sdp.cpp 中使用静态全局变量

char sensor_data_buf[300] = {};

编译一次,当你在swift中编码时,变量应该会变成彩色。

而且你以后可能还要留意导入规则的排序,因为c、c++、objc、objc++方面可能会告诉你你声明了两次。
但这实际上不应该发生,因为这就是额外文件...-Briding-Header.h 的用途。除非您这样做,否则它永远不会在 swift 之外导入,因此它不会触发双重声明警告。

有了这个,我可以快速访问它并打印出我在 c++ 中设置的随机选择值,这意味着它可以工作。

os_log("%u %u", sensor_data_buf.0, sensor_data_buf.3)

.3 是一个索引访问,所以实际上是第 4 个条目,与 c、c++ 中的相同

小心,设置时很重要.. swift 不会等待您的 sensor_data_buf 被实际数据填充,它只是打印我看到的内容。只有当您使用不同的线程访问全局时,它才会变得麻烦。

【讨论】:

  • 只需提交并推送一些更改到 github 中的示例 repo,所以你看。
  • 在我将 mobile_sensor_API-Bridging-Header.h 更改为仅显式声明后仍然存在同样的问题。清理和重建工作区,甚至是自己的 mobile_sensor_API 项目。 Swift 仍然不知道 sensor_data_buf[]。但你的工作?!还有什么需要改变的吗?我会再次从 github 尝试你的。
  • 如果您愿意,可以在您的 github 配置文件中创建一个 repo,然后提交并推送您的项目。我可以查看它。如果我在管道中找到青蛙,请更改它。然后您可以再次删除回购或将其设为私有(如果这对您很重要)。我不知道你对 git 有多熟悉……我可以指导你……我不同意 blabla。
【解决方案2】:

问题是我的 ObjC 静态库项目中的 Swift 不直接与 C++ 接口。

解决方案: 在 ObjC 静态库中为使用 C++ 访问 ObjC 静态库的 Swift 创建 .m 和 .h 包装器。包装器本质上是一个 Swift 调用的函数,它在 C++ 数据结构和 ObjC 静态库的数据结构之间架起一座桥梁,Swift 可以使用。

将“C”接口的接口放入 Swift 的 ...-Bridging-Header.h 中。但是没有 C++ ! 将 C++ 接口(即 extern "C++" ...)放入 .h

【讨论】:

    猜你喜欢
    • 2021-02-02
    • 2021-03-22
    • 2021-11-18
    • 2023-02-21
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    相关资源
    最近更新 更多