Skip to content
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

Allow setting compiled library's path #343

Merged
merged 2 commits into from
Jun 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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