从Zenoh C线程中删除Dart回调-隔离和回调错误

ego6inou  于 2024-01-06  发布在  其他
关注(0)|答案(1)|浏览(79)

我目前在开发一个通过Zenoh协议读取消息的Dart应用程序时遇到了一个具有挑战性的问题。下面是我的问题的分解:
1.我的Dart代码通过Dart:ffi执行原生C代码。(没有问题)
1.然后C代码用数据回调Dart代码(直接回调没有问题)
当我在C代码中引入Zenoh库时,问题就出现了,它创建了一个“订阅者”。每当收到消息时,这个订阅者就会产生线程。这些线程负责处理传入的消息,并将内容回调到我的Dart代码中。
然而,当我尝试从这些线程调用Dart回调函数时,我遇到了以下错误:error: Cannot invoke native callback outside an isolate.
为了解决这个问题,我决定使用Dart:isolate并利用send/ReceivePorts从C线程发送数据。
我不确定我是否正确地处理了这个问题,我也不完全确定我是否完全理解了它。我花了将近四天的时间来解决这个问题,我感到非常困惑和沮丧。
我将非常感谢任何关于如何克服这个障碍并成功地从Zenoh C线程调用Dart回调的见解,建议或指导。提前感谢您的帮助!
Dart Code:

import 'dart:ffi';
import 'package:ffi/ffi.dart';
import 'dart:isolate';

// typedef Request Callback 
typedef RequestCallbackC = Void Function(Int32 port);
typedef RequestCallbackDart = void Function(int port);

class CWrapperZenoh{
  late final DynamicLibrary _zenohLib;
  late final RequestCallbackDart _requestCallbackDart;
  // for native c callback
  late final ReceivePort _receivePort;
  late final SendPort _sendPort;

  CWrapperZenoh(){
    _zenohLib = DynamicLibrary.open("bin/include/lib_c_lib.so");
    _requestCallbackDart = _zenohLib.lookup<NativeFunction<RequestCallbackC>> 
      ('request_callback').asFunction();

    _receivePort = ReceivePort();
    _sendPort = _receivePort.sendPort;

    // listen
    _receivePort.listen((message) {
      print("listen message\n");
      if (message is String) {
        dartCallbackString(message);
      } else if (message is int){
        print(message);
      }
    });
  }

// application calls this to initiate
callFunctions(){
  print("sendport: ${_sendPort.nativePort}");
  _requestCallbackDart(_sendPort.nativePort);
}

static void dartCallbackString(String s) {
  print("Received string from C: $s\n");
}

字符串
}
C库:

#include <string.h>
    #include <stdio.h>
    #include <unistd.h>
    #include "zenoh.h"
    #include "include/dart_api.h"
    #include "include/dart_api_dl.h"
    #include <pthread.h>

    // define Dart callback function
    typedef void (*DartFunction)(const char*);

    z_owned_config_t* config_ptr;
    z_owned_session_t* sessionPtr;
    z_owned_subscriber_t* sub;
    z_owned_closure_sample_t callback;
    Dart_Port dart_port;

    DartFunction dartFunction;

    
    void callbackFuncToDart(const z_sample_t *sample, void *arg);

    void request_callback(Dart_Port port){
        dart_port = port;

        // config
        config_ptr = malloc(sizeof(z_owned_config_t));
        if (config_ptr != NULL) {
            *config_ptr = zc_config_from_file("bin/include/DEFAULT_CONFIG_CONNECT.json5");
        }
        printf("config created\n");
        fflush(stdout);

        // open session
        sessionPtr = (z_owned_session_t*)malloc(sizeof(z_owned_session_t));
        *sessionPtr = z_open(config_ptr);
        
        // subscribing
        z_owned_closure_sample_t callback = z_closure(callbackFuncToDart);
        
        sub = malloc(sizeof(z_owned_subscriber_t));
        *sub = z_declare_subscriber(z_loan(*sessionPtr), z_keyexpr("geometry_msgs/msg/actualSpeed"), z_move(callback), NULL);
    }

    // callback to Dart
    void callbackFuncToDart(const z_sample_t *sample, void *arg) {
        
        // Create a SendPort to communicate with Dart isolate
        Dart_Handle sendPort = Dart_NewSendPort(dart_port);

        // Check if creating the SendPort was successful
        if (!Dart_IsError(sendPort)) {
            Dart_CObject message;
            message.type = Dart_CObject_kInt32;
            message.value.as_int32 = 1;

            // Send the message using the SendPort
            if (Dart_PostCObject(dart_port, &message)){
                printf("Message sent\n");
                fflush(stdout);
            } else {
                printf("Failed to create SendPort\n");
                fflush(stdout);
            }   
        }

        //--Removed old irelevant code. comment relevant for my first threaded callback attempt--
        //dartFunction(str);    // different thread id than Darts "Main isolate". therefore i get the following: "error: Cannot invoke native callback outside an isolate."
                                            
    }

7eumitmz

7eumitmz1#

自从我发布这个问题以来发生了很多事情,我不知道是什么原因导致了这个确切的问题。
在我的C库中,

// Initialize `dart_api_dl.h`
DART_EXPORT intptr_t InitDartApiDL(void* data) {
  return Dart_InitializeApiDL(data);
}

字符串
然后在我的Dart构造函数中调用它

ZenohWrapper() {
  _zenohLib = DynamicLibrary.open('dirToLib/lib.so');
  _initializeZenohFunctions();
  final initializeApi = _zenohLib.lookupFunction<IntPtr Function(Pointer<Void>), int Function(Pointer<Void>)>("InitDartApiDL");
}

相关问题