diff --git a/src/dart/example/.gitignore b/src/dart/example/.gitignore index 0fa6b675c0..e717a6f12b 100644 --- a/src/dart/example/.gitignore +++ b/src/dart/example/.gitignore @@ -14,6 +14,7 @@ *.ipr *.iws .idea/ +resource/ # The .vscode folder contains launch configuration and tasks you configure in # VS Code which you may wish to be included in version control, so this line diff --git a/src/dart/example/lib/main.dart b/src/dart/example/lib/main.dart index b95ada0972..52f2461a64 100644 --- a/src/dart/example/lib/main.dart +++ b/src/dart/example/lib/main.dart @@ -8,6 +8,7 @@ import 'package:maa_core/typedefs.dart'; import "package:path/path.dart" as p; void main() { + print(Directory.current.path); runApp(const MyApp()); } @@ -56,16 +57,18 @@ class MyHomePage extends StatefulWidget { class _MyHomePageState extends State { late MaaCore _asst; - List _logs =[]; + List _logs = []; @override void initState() { setState(() { - _asst = MaaCore(p.join(p.current, 'linux')); + _asst = MaaCore(p.current, callback); + _asst.connect('adb', 'emulator-5554'); }); super.initState(); } - void callback(dynamic message) { + + void callback(String message) { setState(() { _logs.add(message); }); @@ -81,16 +84,15 @@ class _MyHomePageState extends State { // than having to individually change instances of widgets. return Scaffold( - appBar: AppBar( - // Here we take the value from the MyHomePage object that was created by - // the App.build method, and use it to set our appbar title. - title: Text(widget.title), - ), - body: Center( - child: Column( - children: _logs.map((e) => Text(e)).toList(), + appBar: AppBar( + // Here we take the value from the MyHomePage object that was created by + // the App.build method, and use it to set our appbar title. + title: Text(widget.title), ), - ) - ); + body: Center( + child: Column( + children: _logs.map((e) => Text(e)).toList(), + ), + )); } } diff --git a/src/dart/lib/maa_core.dart b/src/dart/lib/maa_core.dart index ea63a26810..1db8bd8d8c 100644 --- a/src/dart/lib/maa_core.dart +++ b/src/dart/lib/maa_core.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:ffi'; import 'dart:convert'; import 'dart:isolate'; @@ -7,6 +8,9 @@ import 'package:path/path.dart' as p; class MaaCore implements MaaCoreInterface { late Assistant _asst; + late AsstLoadResourceFunc _asstLoadResource; + late AsstCreateFunc _asstCreate; + late AsstCreateExFunc _asstCreateEx; late AsstConnectFunc _asstConnect; late AsstDestroyFunc _asstDestroy; late AsstAppendTaskFunc _asstAppendTask; @@ -16,39 +20,67 @@ class MaaCore implements MaaCoreInterface { late AsstCtrlerClickFunc _asstCtrlerClick; late AsstGetVersionFunc _asstGetVersion; late AsstLogFunc _asstLog; - static bool resourceLoaded = false; + static bool _resourceLoaded = false; late ReceivePort? _receivePort; + static bool _apiInited = false; ReceivePort? get receivePort => _receivePort; - late Pointer _pointer; + late StreamSubscription _portSubscription; + late List _allocated; + static Future get platformVersion async { return Future(() => '0.0.1'); } - static bool loadResource(DynamicLibrary lib, String resourceDir) { - final AsstLoadResourceFunc asstLoadResource = - lib.lookup('AsstLoadResource').asFunction(); - if (!resourceLoaded) { - return asstLoadResource(resourceDir.toNativeUtf8()); - } - return true; + void _loadResource(String path) { + final strPtr = toManagedString(path); + final result = _asstLoadResource(strPtr); + _resourceLoaded = _resourceLoaded || result; } - MaaCore(String libDir, [Function(dynamic)? callback]) { - + MaaCore(String libDir, [Function(String)? callback]) { _loadCppLib(libDir); - final _createWithDartPort = loadAsstCreateDart(libDir); - _receivePort = ReceivePort(); - final portPtr = malloc.allocate(sizeOf()); - portPtr.value = _receivePort!.sendPort.nativePort; - _asst = _createWithDartPort(portPtr); - if (callback != null) { - _receivePort!.listen(callback); + if (!_apiInited) { + final callbackLib = DynamicLibrary.open(p.join(libDir, 'libCallback.so')); + final InitDartApiFunc initNativeApi = + callbackLib.lookup('init_dart_api').asFunction(); + initNativeApi(NativeApi.initializeApiDLData); + _apiInited = true; } + + _allocated = []; + if (!_resourceLoaded) { + _loadResource(libDir); + } + _receivePort = ReceivePort(); + final nativePort = _receivePort!.sendPort.nativePort; + final portPtr = malloc.allocate(sizeOf()); + _asst = _asstCreateEx(nativeCallback, portPtr.cast()); + _allocated.add(portPtr); + portPtr.value = nativePort; + if (callback != null) { + _portSubscription = _receivePort!.listen(_wrapCallback(callback)); + } + } + + void Function(dynamic) _wrapCallback(void Function(String) cb) { + return (dynamic data) { + // c will manage the memory for the string + String msg = data; + cb(msg); + }; + } + + Pointer get nativeCallback { + return DynamicLibrary.open('./libCallback.so') + .lookup('callback'); } void _loadCppLib(String libDir) { final lib = DynamicLibrary.open(p.join(libDir, 'libMeoAssistant.so')); - + _asstLoadResource = + lib.lookup('AsstLoadResource').asFunction(); + _asstCreate = lib.lookup('AsstCreate').asFunction(); + _asstCreateEx = lib.lookup('AsstCreateEx').asFunction(); _asstConnect = lib.lookup('AsstConnect').asFunction(); _asstDestroy = lib.lookup('AsstDestroy').asFunction(); _asstAppendTask = @@ -65,24 +97,24 @@ class MaaCore implements MaaCoreInterface { } @override - bool connect({ - required String adbPath, - required String address, - String config = '', - }) { + bool connect(adbPath, address, [config = '']) { return _asstConnect( _asst, - adbPath.toNativeUtf8(), - address.toNativeUtf8(), - config.toNativeUtf8(), + toManagedString(adbPath), + toManagedString(address), + toManagedString(config), ); } @override void destroy() { if (_receivePort != null) { + _portSubscription.cancel(); _receivePort!.close(); - malloc.free(_pointer); + } + while (_allocated.isNotEmpty) { + final ptr = _allocated.removeLast(); + malloc.free(ptr); } _asstDestroy(_asst); } @@ -92,8 +124,8 @@ class MaaCore implements MaaCoreInterface { final json = jsonEncode(params ?? {}); final taskId = _asstAppendTask( _asst, - type.toNativeUtf8(), - json.toNativeUtf8(), + toManagedString(type), + toManagedString(json), ); return taskId; } @@ -104,7 +136,7 @@ class MaaCore implements MaaCoreInterface { final result = _asstSetTaskParams( _asst, taskId, - json.toNativeUtf8(), + toManagedString(json), ); return result; } @@ -131,23 +163,12 @@ class MaaCore implements MaaCoreInterface { @override void log(String logLevel, String msg) { - _asstLog(logLevel.toNativeUtf8(), msg.toNativeUtf8()); + _asstLog(toManagedString(logLevel), toManagedString(msg)); + } + + Pointer toManagedString(String str) { + final ptr = str.toNativeUtf8(); + _allocated.add(ptr); + return ptr; } } - -AsstCreateDartFunc loadAsstCreateDart(String libPath) { - final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); - return lib - .lookup('AsstCreateWithDartPort') - .asFunction(); -} - -InitDartVMFunc loadInitDartVM(String libPath) { - final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); - return lib.lookup('InitDartVM').asFunction(); -} - -CleanUpDartVMFunc loadCleanUpDartVM(String libPath) { - final lib = DynamicLibrary.open(p.join(libPath, 'libMeoAssistantDart.so')); - return lib.lookup('CleanUpDartVM').asFunction(); -} diff --git a/src/dart/lib/typedefs.dart b/src/dart/lib/typedefs.dart index d3e6fac7d9..10f75e6930 100644 --- a/src/dart/lib/typedefs.dart +++ b/src/dart/lib/typedefs.dart @@ -3,14 +3,14 @@ import "dart:ffi"; import "package:ffi/ffi.dart"; typedef Assistant = Pointer; -typedef AsstCallbackNative - = NativeFunction)>; - -typedef AsstCallbackFunc = Void Function(Int32, StringPtr, Pointer); +typedef AsstCallbackFunc = void Function(int, Pointer, Pointer); +typedef AsstCallbackNative = NativeFunction, Pointer)>; // AsstCreateEx typedef AsstCreateDartFunc = Assistant Function(Pointer); typedef AsstCreateDartNative = NativeFunction)>; +typedef AsstCreateExFunc = Assistant Function(Pointer, Pointer); +typedef AsstCreateExNative = NativeFunction; // AsstCreate typedef AsstCreateFunc = Assistant Function(); @@ -65,8 +65,8 @@ typedef TaskId = int; typedef TaskIdNative = Int32; typedef StringPtr = Pointer; -typedef InitDartVMFunc = void Function(Pointer); -typedef InitDartVMNative = NativeFunction)>; +typedef InitDartApiFunc = void Function(Pointer); +typedef InitDartApiNative = NativeFunction)>; typedef CleanUpDartVMFunc = void Function(); @@ -74,8 +74,7 @@ typedef CleanUpDartVMNative = NativeFunction; abstract class MaaCoreInterface { void destroy(); - bool connect( - {required String adbPath, required String address, String config = ''}); + bool connect(String adbPath, String address,[String config = '']); TaskId appendTask(String type, [Map? params]); bool setTaskParams(TaskId taskId, [Map? params]); bool start(); diff --git a/src/dart/native/CMakeLists.txt b/src/dart/native/CMakeLists.txt index 0380552352..b9508118c1 100644 --- a/src/dart/native/CMakeLists.txt +++ b/src/dart/native/CMakeLists.txt @@ -1,27 +1,9 @@ cmake_minimum_required(VERSION 2.8) -project(MeoAssistantArknightsDart) +project(callback) -if (WIN32) - add_compile_options("$<$:/utf-8>") - add_compile_options("$<$:/utf-8>") - add_compile_options("$<$:/MP>") - add_compile_options("$<$:/MP>") +add_library(Callback SHARED callback.c dart_api_dl.c) - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") -endif() - -add_compile_options("$<$:/W4>") -add_compile_options("$<$>:-Wall;-Wextra;-Wpedantic>") -add_library(MeoAssistantDart SHARED src/AsstDartApi.cpp) -set(CMAKE_CXX_STANDARD 17) -set(MAA_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../..") - - -include_directories("include" "${MAA_ROOT}/include" "dart" "dart/internal") -find_library(MeoAssistant PATHS "${CMAKE_CURRENT_SOURCE}/lib") - - -target_link_libraries(MeoAssistantDart PUBLIC ${MeoAssitant}) -install(TARGETS MeoAssistantDart DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../linux") -install(FILES lib/libMeoAssistant.so DESTINATION "${CMAKE_CURRENT_SOURCE_DIR}/../linux") +target_include_directories(Callback PUBLIC + "${CMAKE_CURRENT_SOURCE_DIR}/include" + "${CMAKE_CURRENT_SOURCE_DIR}/include/internal" +) diff --git a/src/dart/native/callback.c b/src/dart/native/callback.c new file mode 100644 index 0000000000..ab3200e358 --- /dev/null +++ b/src/dart/native/callback.c @@ -0,0 +1,32 @@ +#include "dart_api_dl.h" +#include +#include +void callback(int, const char *, void *); +void init_dart_api(void *); +void init_dart_api(void *api_data) { + Dart_InitializeApiDL(api_data); +} + +void callback(int retval, const char *json_str, void *custom_arg) { + Dart_Port port = *(Dart_Port *)custom_arg; + + + int n_digits = 1; + int k = retval; + while (k > 10) { + n_digits++; + k /= 10; + } + Dart_CObject obj; + int required_len = n_digits + strlen(json_str) + 1; + char retstr[required_len]; + retstr[required_len-1] = 0; + sprintf(retstr, "{\"retval\": %d, payload: \"%s\" }", retval, json_str); + obj.type = Dart_CObject_kString; + obj.value.as_string = retstr; + printf("C: Sending Pointer %ld to dart through port %ld\n", (int64_t)json_str, port); + char res = Dart_PostCObject_DL(port, &obj); + if (res == 0) { + printf("C: Failed to send message to Dart\n"); + } +} \ No newline at end of file diff --git a/src/dart/native/dart/dart_api_dl.c b/src/dart/native/dart_api_dl.c similarity index 100% rename from src/dart/native/dart/dart_api_dl.c rename to src/dart/native/dart_api_dl.c diff --git a/src/dart/native/include/AsstDartApi.h b/src/dart/native/include/AsstDartApi.h deleted file mode 100644 index 5e04e495a0..0000000000 --- a/src/dart/native/include/AsstDartApi.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef ASST_DART_API_H_ -#define ASST_DART_API_H_ -#include "dart_api.h" -#include "AsstCaller.h" - -DART_EXPORT AsstHandle AsstCreateWithDartPort(Dart_Port *dart_port); -DART_EXPORT void InitDartVM(void *data); - -#endif \ No newline at end of file diff --git a/src/dart/native/dart/dart_api.h b/src/dart/native/include/dart_api.h similarity index 100% rename from src/dart/native/dart/dart_api.h rename to src/dart/native/include/dart_api.h diff --git a/src/dart/native/dart/dart_api_dl.h b/src/dart/native/include/dart_api_dl.h similarity index 100% rename from src/dart/native/dart/dart_api_dl.h rename to src/dart/native/include/dart_api_dl.h diff --git a/src/dart/native/dart/dart_native_api.h b/src/dart/native/include/dart_native_api.h similarity index 100% rename from src/dart/native/dart/dart_native_api.h rename to src/dart/native/include/dart_native_api.h diff --git a/src/dart/native/dart/dart_tools_api.h b/src/dart/native/include/dart_tools_api.h similarity index 100% rename from src/dart/native/dart/dart_tools_api.h rename to src/dart/native/include/dart_tools_api.h diff --git a/src/dart/native/dart/dart_version.h b/src/dart/native/include/dart_version.h similarity index 100% rename from src/dart/native/dart/dart_version.h rename to src/dart/native/include/dart_version.h diff --git a/src/dart/native/dart/internal/dart_api_dl_impl.h b/src/dart/native/include/internal/dart_api_dl_impl.h similarity index 100% rename from src/dart/native/dart/internal/dart_api_dl_impl.h rename to src/dart/native/include/internal/dart_api_dl_impl.h diff --git a/src/dart/native/src/AsstDartApi.cpp b/src/dart/native/src/AsstDartApi.cpp deleted file mode 100644 index 41d9d4d061..0000000000 --- a/src/dart/native/src/AsstDartApi.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "AsstDartApi.h" -#include "AsstCaller.h" -#include "dart_api.h" -#include "dart_api_dl.h" - -#include -#include - -DART_EXPORT AsstHandle AsstCreateWithDartPort(Dart_Port *dart_port) -{ - std::cout << "CPP: Dart_Port Pointer " << dart_port << std::endl; - std::cout << "CPP: Native Port: " << *dart_port << std::endl; - AsstApiCallback dart_cb = [](int msg, const char* detail, void* custom_arg) - { - Dart_CObject obj; - obj.type = Dart_CObject_kString; - obj.value.as_string = const_cast(detail); - Dart_Port port = *(Dart_Port *)custom_arg; - std::cout << "CPP: Native Port in closure: " << port << std::endl; - bool res = Dart_PostCObject(port, &obj); - if (!res) { - std::cerr << "CPP: Dart_PostCObject failed" << std::endl; - } else { - std::cout << "CPP: Successfully Sent message: " << detail << std::endl; - } - }; - - return AsstCreateEx(dart_cb, dart_port); -} - -DART_EXPORT void InitDartVM(void *data) -{ - std::cout << "CPP: InitDartVM" << std::endl; - Dart_InitializeParams* params = (Dart_InitializeParams*) data; - char* res = Dart_Initialize(params); - if (res) { - std::cerr << "CPP: Dart_Initialize failed:" << res << std::endl; - } else { - std::cout << "CPP: Dart_Initialize success" << std::endl; - } - free(res); -} \ No newline at end of file