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
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
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
insdp_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
and a tiny change because you where going with a static global in sdp.cpp
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.
.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.