Skip to content

Commit

Permalink
Merge pull request #343 from cunarist/setting-compiled-lib-path
Browse files Browse the repository at this point in the history
Allow setting compiled library's path
  • Loading branch information
temeddix authored Jun 1, 2024
2 parents 20e1013 + 5f30cb9 commit 7905a57
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 5 deletions.
22 changes: 22 additions & 0 deletions documentation/docs/frequently-asked-questions.md
Original file line number Diff line number Diff line change
Expand Up @@ -308,3 +308,25 @@ These links might be a help:
- https://kazlauskas.me/entries/writing-proper-buildrs-scripts
- https://github.com/RustAudio/rodio/issues/404
- https://github.com/breez/c-breez/issues/553

### How do I set the path to a compiled dynamic library?

You might want to run your app on embedded devices. However, you may encounter this error when running your app on a non-major platform:

```
Failed to load dynamic library 'libhub.so': libhub.so: cannot open shared object file: No such file or directory
```

In this case, you can specify a path that points to the compiled Rust library. Simply provide a string path to your dynamic library file.

```dart title="lib/main.dart"
import './messages/generated.dart';
async void main() {
await initializeRust(compiledLibPath: "/path/to/library/libhub.so");
...
}
...
```

This provided path will be used for finding dynamic library files on native platforms with Dart's `DynamicLibrary.open([compiledLibPath])`, and for loading the JavaScript module on the web with `import init, * as wasmBindings from "[compiledLibPath]"`.
3 changes: 2 additions & 1 deletion flutter_ffi_plugin/bin/src/message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,8 @@ hash_map.insert(
import 'dart:typed_data';
import 'package:rinf/rinf.dart';
Future<void> initializeRust() async {
Future<void> initializeRust({String? compiledLibPath}) async {
setCompiledLibPath(compiledLibPath);
await prepareInterface(handleRustSignal);
startRustLogic();
}
Expand Down
16 changes: 13 additions & 3 deletions flutter_ffi_plugin/lib/rinf.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ import 'src/exports.dart';

export 'src/interface.dart' show RustSignal;

/// Sets the exact file path of the dynamic library
/// compiled from the `hub` crate.
/// On the web, this function sets the path to the JavaScript module
/// that needs to be loaded.
/// This function might not be necessary for major platforms
/// but can be useful when the app runs on embedded devices.
void setCompiledLibPath(String? path) {
setCompiledLibPathExtern(path);
}

/// Prepares the native interface
/// needed to communicate with Rust.
Future<void> prepareInterface(HandleRustSignal handleRustSignal) async {
Expand All @@ -18,9 +28,9 @@ void startRustLogic() async {
}

/// Terminates all Rust tasks.
/// Doing so before closing the Flutter app
/// can prevent potential memory errors that may occur
/// when Rust attempts to send data after the Dart VM has been turned off.
/// Calling this function before closing the Flutter app
/// can prevent potential resource leaks that may occur
/// if the Rust side is abruptly terminated.
/// Please note that on the web, this function does not have any effect,
/// as tasks are managed by the JavaScript runtime, not Rust.
void stopRustLogic() async {
Expand Down
4 changes: 4 additions & 0 deletions flutter_ffi_plugin/lib/src/interface_os.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import 'dart:isolate';
import 'interface.dart';
import 'dart:convert';

void setCompiledLibPathExtern(String? path) {
setDynamicLibPath(path);
}

Future<void> prepareInterfaceExtern(
HandleRustSignal handleRustSignal,
) async {
Expand Down
4 changes: 4 additions & 0 deletions flutter_ffi_plugin/lib/src/interface_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ import 'interface.dart';
import 'dart:async';
import 'dart:convert';

void setCompiledLibPathExtern(String? path) {
setJsLibPath(path);
}

Future<void> prepareInterfaceExtern(
HandleRustSignal handleRustSignal,
) async {
Expand Down
12 changes: 12 additions & 0 deletions flutter_ffi_plugin/lib/src/load_os.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
import 'dart:io' as io;
import 'dart:ffi';

String? dynamicLibPath;
final rustLibrary = loadRustLibrary();

void setDynamicLibPath(String? path) {
dynamicLibPath = path;
}

DynamicLibrary loadRustLibrary() {
// Use provided dynamic library path if possible.
final path = dynamicLibPath;
if (path != null) {
return DynamicLibrary.open(path);
}

// Otherewise, use the default path.
if (io.Platform.isLinux) {
return DynamicLibrary.open('libhub.so');
} else if (io.Platform.isAndroid) {
Expand Down
11 changes: 10 additions & 1 deletion flutter_ffi_plugin/lib/src/load_web.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,17 @@ import 'dart:js' as js;
import 'dart:html';
import 'dart:async';

String? jsLibPath;

// When Dart performs hot restart,
// the `rinf` object is already defined
// as a global JavaScript variable.
final wasAlreadyLoaded = js.context.hasProperty("rinf");

void setJsLibPath(String? path) {
jsLibPath = path;
}

Future<void> loadJsFile() async {
if (wasAlreadyLoaded) {
return;
Expand All @@ -17,10 +23,13 @@ Future<void> loadJsFile() async {
final loadCompleter = Completer<void>();
js.context['completeRinfLoad'] = loadCompleter.complete;

// Use the default JavaScript path unless provided.
final path = jsLibPath ?? "/pkg/hub.js";

final scriptElement = ScriptElement();
scriptElement.type = "module";
scriptElement.innerHtml = '''
import init, * as wasmBindings from "/pkg/hub.js";
import init, * as wasmBindings from "$path";
await init();
window.rinf = { ...wasmBindings };
completeRinfLoad();
Expand Down

0 comments on commit 7905a57

Please sign in to comment.