-
-
Notifications
You must be signed in to change notification settings - Fork 335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP initial commit for issue 327: Add Swift binding #342
Changes from all commits
88a657d
5affb16
4623103
6945a3d
7b1b065
14f6654
faed7e1
7e29b87
9353313
bcf8ee3
7193cf8
d416daf
ecc5587
7abad5e
2ffd587
2f4ef9d
e99372e
6f6f7b8
4525f96
4cd7580
8f1811f
2b54630
b11e4e2
a02aa07
c2de9da
8ed0bd0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -127,6 +127,47 @@ Rust | |
cd brainflow | ||
cargo build --features generate_binding | ||
|
||
Swift | ||
------- | ||
|
||
The following instructions are tested on a MacBook Pro M1 using Xcode 13.4 and macOS Monterey 12.3.1. | ||
|
||
The Xcode build scheme is for destination "My Mac (Rosetta)". The dylibs are universal (built for macos-arm64_x86_64.) The target build architecture is set to $(ARCHS_STANDARD). | ||
|
||
High level steps: | ||
- Build the universal dylibs | ||
- Copy the entire BrainFlow package from swift-package into the top level folder of your Xcode project. | ||
- Copy the BrainFlowBindings subfolder from the package into your target app group. | ||
- Set the briding header | ||
- Compile the package | ||
- Set the package dependency | ||
- Build | ||
|
||
Assumptions: | ||
- the BrainFlow repo is cloned to /Users/myusername/brainflow | ||
- your Xcode project is located at /Users/myusername/myproject | ||
- within your Xcode project is a group named myapp | ||
|
||
Detailed steps: | ||
- in a shell such as iTerm2: | ||
|
||
cd /Users/myusername/brainflow/swift-package | ||
./build_package_macOS.sh | ||
|
||
- Copy the BrainFlow folder and its entire contents from /Users/myusername/brainflow/swift-package to /Users/myusername/myproject. | ||
- In Xcode select the top-level project and then click File->Add Packages...Add Local... | ||
- Select /Users/myusername/myproject/BrainFlow. Click Open. | ||
- Drag-and-drop the BrainFlowBindings subfolder from myproject/Packages/BrainFLow/Sources into myproject/myapp. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets create a github actions artifacts with all precompiled libraries, example can be found here https://github.com/brainflow-dev/brainflow/actions/runs/2572045283 https://github.com/brainflow-dev/brainflow/blob/master/.github/workflows/deploy_cpp_libs.yml#L104 We can trigger all required scripts to build it(build_package_macos.sh that should be moved to build.py) in CI and upload binaries, so other people will not even need to run it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe instead github artifacts we can publish to aws(run_unix workflow does it currently) I can take care of publishing and packaging but need to build package inside CI first |
||
- A dialog will pop up. In the dialog check the "Copy items if needed" box, select "Create groups", and check the box(es) next to your target(s). | ||
- In the build settings of your build target, search for "bridging". Set the Objective-C Bridging Header to "BrainFlow/BrainFlow.h". | ||
- In the scheme selector at the top of the window, select the BrainFlow scheme for "My Mac (Rosetta)". | ||
- Press Command-B (build) to build the package. | ||
- In the General settings of your build target, scroll down to Frameworks, Libraries and Embedded Content. | ||
- Click the plus button and select the BrainFlow package under the Workspace group. | ||
- In the scheme selector at the top of the window, select the myapp scheme for "My Mac (Rosetta)". | ||
- Press Command-B (build) to build the target. | ||
|
||
|
||
Docker Image | ||
-------------- | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -492,3 +492,9 @@ Notebooks | |
./notebooks/brainflow_mne | ||
./notebooks/denoising | ||
./notebooks/band_power | ||
|
||
Swift | ||
------ | ||
|
||
.. literalinclude:: ../swift-package/BrainFlow/Tests/BrainFlowTests/BrainFlowCITests.swift | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we separate them to match the structure with other languages? all of them have exactly the same code samples and they are separated. also lets add it before notebooks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
:language: swift |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.DS_Store | ||
/.build | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// | ||
// Created by Scott Miller on 4/9/22. | ||
// | ||
|
||
#ifndef BrainFlow_h | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lets replace by pragma once, its used in all other headers and lets make it consistent There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok |
||
#define BrainFlow_h | ||
|
||
#include <board_controller.h> | ||
#include <data_handler.h> | ||
#include <board_info_getter.h> | ||
#include <ml_module.h> | ||
|
||
#endif /* BrainFlow_h */ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this file be in the repo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no |
||
"object": { | ||
"pins": [ | ||
{ | ||
"package": "swift-numerics", | ||
"repositoryURL": "https://github.com/apple/swift-numerics.git", | ||
"state": { | ||
"branch": null, | ||
"revision": "0a5bc04095a675662cf24757cc0640aa2204253b", | ||
"version": "1.0.2" | ||
} | ||
} | ||
] | ||
}, | ||
"version": 1 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// swift-tools-version:5.3 | ||
import PackageDescription | ||
|
||
let package = Package( | ||
name: "BrainFlow", | ||
platforms: [ | ||
.macOS(.v10_15), .iOS(.v13) | ||
], | ||
products: [ | ||
// Products define the executables and libraries a package produces, and make them visible to other packages. | ||
.library(name: "BrainFlow", | ||
targets: ["BrainFlow", "BoardController", "DataHandler", "MLModule", "BrainBitLib"]) | ||
], | ||
dependencies: [ | ||
.package(name: "swift-numerics", | ||
url: "https://github.com/apple/swift-numerics.git", .upToNextMajor(from: "1.0.0")) | ||
], | ||
targets: [ | ||
.target( | ||
name: "BrainFlow", | ||
dependencies: [.product(name: "Numerics", package: "swift-numerics"), | ||
.target(name: "BoardController")] | ||
), | ||
.binaryTarget( | ||
name: "BoardController", | ||
path: "BoardController.xcframework" | ||
), | ||
.binaryTarget( | ||
name: "DataHandler", | ||
path: "DataHandler.xcframework" | ||
), | ||
.binaryTarget( | ||
name: "MLModule", | ||
path: "MLModule.xcframework" | ||
), | ||
.binaryTarget( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. actually also there are other binaries, I think we should also all libsimpleble.dylib,musebglib,ganglionbglib and libonnxruntime.dylib To see some of these libs you need to compile using build.py with |
||
name: "BrainBitLib", | ||
path: "BrainBitLib.xcframework" | ||
), | ||
.testTarget( | ||
name: "BrainFlowTests", | ||
dependencies: ["BrainFlow", .product(name: "Numerics", package: "swift-numerics")], | ||
sources: ["BoardShimTests.swift", | ||
"BrainFlowCItests.swift", | ||
"BrainFlowTests.swift", | ||
"DataFilterTests.swift"] | ||
) | ||
] | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
# BrainFlow | ||
|
||
Swift bindings for the BrainFlow C++ API. Contributed by Scott Miller for Aeris Rising, LLC. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what is it? |
||
import Foundation | ||
|
||
struct dummy { | ||
let num = 1 | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// | ||
// BoardDescription.swift | ||
// a Swift reimagining of BrainFlow's board_description data type | ||
// | ||
// Created by Scott Miller for Aeris Rising, LLC on 8/23/21. | ||
// | ||
import Foundation | ||
//import BrainFlow | ||
|
||
struct BoardDescription: Codable, Equatable { | ||
let package_num_channel: Int32 | ||
let timestamp_channel: Int32 | ||
let accel_channels: [Int32]? | ||
let ecg_channels: [Int32]? | ||
let eeg_channels: [Int32]? | ||
let eeg_names: String? | ||
let emg_channels: [Int32]? | ||
let eog_channels: [Int32]? | ||
let marker_channel: Int32? | ||
let name: String? | ||
let num_rows: Int32? | ||
let sampling_rate: Int32? | ||
let battery_channel: Int32? | ||
let eda_channels: [Int32]? | ||
let gyro_channels: [Int32]? | ||
let ppg_channels: [Int32]? | ||
let resistance_channels: [Int32]? | ||
let temperature_channels: [Int32]? | ||
|
||
// decode the input JSON into self: | ||
init(_ descriptionJSON: String) throws { | ||
guard descriptionJSON != "" else { | ||
throw BrainFlowException("Nil board description JSON", .JSON_NOT_FOUND_ERROR) | ||
} | ||
|
||
let decoder = JSONDecoder() | ||
let jsonData = Data(descriptionJSON.utf8) | ||
|
||
do { | ||
let json = try decoder.decode(type(of: self), from: jsonData) | ||
self = json | ||
} catch { | ||
try? BoardShim.logMessage(.LEVEL_CRITICAL, "board description JSON decoding error:\n \(error)") | ||
throw BrainFlowException("Invalid board description JSON", .NO_SUCH_DATA_IN_JSON_ERROR) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its better to add it to build.py and get rid off shell scripts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also build.py builds dylibs so it will decrease the number of steps
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will take a look.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the examples, do you want something like this:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, exactly. R is not the best example but you got the idea. Would be better to use python as a reference. You can also find them here https://github.com/brainflow-dev/brainflow/blob/master/docs/Examples.rst(will also need to add swift examples to this page)