skip to Main Content

Xcode build doesn’t recognize a byte array sensor_data_bytes defined in C++ .cpp file.

It does, however recognize a char variable defined in same files and also recognizes unsigned sensor_data_bytes.

func peripheral() receives BLE notification data which it needs to copy to C++ char array sensor_data_bytes.

STRUCTURE

My workspace Objective-C app project ‘sim_backend_UI‘ imports two static lib projects (A & B).

A) ‘mobile_sensor_API‘ contains:

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

B) ‘mobile_hub‘ contains:

sdp_BLE.hpp  
sdp.cpp 

CODE

// 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;
        }
    }

    . . .
}

2

Answers


  1. Chosen as BEST ANSWER

    The problem was that Swift in my ObjC static lib project doesn't interface directly with C++.

    Solution: Create .m and .h wrapper, within the ObjC static lib, for Swift that accesses the ObjC static lib with C++. The wrapper is essentially a function that the Swift calls which bridges between the C++ data structures and the data structures of the ObjC static lib, which Swift is okay to use.

    Put interface to 'C' interface into ...-Bridging-Header.h for Swift. But no C++ ! Put C++ interface (ie. extern "C++" ...) into .h


  2. indeed there is a scope problem.

    your swift module does not know about the global char sensor_data_buf[300].
    I guess that is because the macro #ifndef BLE_bridge_h in sdp_BLE.hpp keeps it from becoming public in full in the bridging header. The pre-processor possibly thinks everything is fine but the macro stops it from exposing properly.

    Just testet how to declare it in our hub_lib project from days ago..

    write an explicit declaration in the bridging header

    // 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];
    

    and a tiny change because you where going with a static global in sdp.cpp

    char sensor_data_buf[300] = {};
    

    compile once, the variable should become coloured when you code in swift.

    And you may have to keep an eye on the sorting of import rules later on, because the c, c++, objc, objc++ side may tell you that you declared twice.
    But that should actually not happen because thats what the extra file ...-Briding-Header.h is for. It never gets imported outside swift unless you do so, so it can not trigger doubled declaration warnings.

    With this i was able to access it in swift and print out a random choosen value i did set in c++, which meant it works.

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

    .3 is an indexed access so actually the 4th entry, same as in c, c++

    be careful, it matters when it is set.. swift does not wait for your sensor_data_buf to be filled with actual data, it just prints what i sees. It should only become trouble-some when you work with different threads accessing the global.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search