Skip to content

"Cannot invoke a native callback outside of an isolate" Flutter FFI #55626

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

Closed
sanjaygholap opened this issue May 2, 2024 · 4 comments
Closed
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi

Comments

@sanjaygholap
Copy link

"Cannot invoke a native callback outside of an isolate".Within the C++ DLL file. A separate thread with a callback was started internally. we also check for NativeCallable.listener but issue is still persistent

@sanjaygholap sanjaygholap changed the title "Cannot invoke a native callback outside of an isolate" "Cannot invoke a native callback outside of an isolate" Flutter FFI May 2, 2024
@lrhn lrhn added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi labels May 3, 2024
@dcharkes
Copy link
Contributor

dcharkes commented May 3, 2024

we also check for NativeCallable.listener but issue is still persistent

Are you sure? This error message can only occur with NativeCallable.isolateLocal.

Could you provide a minimal reproduction on a GitHub repo?

@dcharkes dcharkes assigned liamappelbe and unassigned dcharkes May 3, 2024
@sanjaygholap
Copy link
Author

Thank you for your response.

We call CPP dll in Flutter using Flutter ffi. This is our CPP function in dll.

extern "C" __declspec(dllexport) void StartServerSession (const char* Name,const char* js,int& sessionID,int& ERESULT,void(eventhandler)(const char,int))
export "C"__declspec(dllexport) void InitializeServer(void(eventhandler)(const char,int)){ PtrObj->Initialize(eventhandler); }

final DynamicLibrary DllPath = DynamicLibrary.open('path to dll');
typedef InitializeFunc = Void Function(Pointer<Void> eventhandler);
typedef InitializeFun = void Function(Pointer<Void> eventhandler);

typedef StartServerSessionC = Void Function(Pointer<Utf8> Name, Pointer<Utf8> js, Pointer<Pointer<Int32>> sessionID, Pointer<Pointer<Int32>> ERESULT,Pointer<Void> eventhandler);
typedef StartServerSession = void Function(Pointer<Utf8> Name, Pointer<Utf8> js, Pointer<Pointer<Int32>> sessionID, Pointer<Pointer<Int32>> ERESULT,Pointer<Void> eventhandler);

void eventHandler(Pointer<Utf8> response, int length) {
  print('Response: ${response.cast<Utf8>.toDartString()}');
}


final initialize = DllPath.lookupFunction<InitializeFunc , InitializeFun>('Initialize');

final startServerSession = DllPath
    .lookupFunction<StartServerSessionC, StartServerSession>('StartServerSession');


void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('FFI Demo')),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              // Example usage of the FFI functions
                await callStartServerIsolate();
            },
            child: Text('Call DLL Function'),
          ),
        ),
      ),
    );
  }
}

void StartServerFunction(SendPort sendPort) 
{
   Pointer<Utf8> name = ('path to second dll'.toNativeUtf8());
   Pointer<Utf8> js = {json value}.toNativeUtf8();
           
   final sessionID = calloc<Int32>();
   final ERESULT = calloc<Int32>();
   initialize (Pointer.fromFunction<Void Function(Pointer<Utf8>, Int32)>(eventHandler)as Pointer<Void>);
   startServerSession (
							   name,
                               js,
                               sessionID as Pointer<Pointer<Int32>>,
                               ERESULT as Pointer<Pointer<Int32>>, 
                               Pointer.fromFunction<Void Function(Pointer<Utf8>, Int32)>(eventHandler)as Pointer<Void>);
    
    sendPort.send("task Complete");
}
Future<Void> callStartServerIsolate()async{
final receivePort = ReceivePort();
final sendPort = receivePort.sendPort;
await Isolate.spawn(StartServerFunction,sendPort)
}

@liamappelbe
Copy link
Contributor

Pointer.fromFunction is a sync callback. You're using it in two places in StartServerFunction. Use NativeCallable.listener instead.

@sanjaygholap
Copy link
Author

@liamappelbe sir and @dcharkes sir thank you issue is resloved

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi
Projects
None yet
Development

No branches or pull requests

4 participants