0

I have a dart method that invokes some C code using dart:ffi. When the C code fails (for example due to some memory violation), I don't get any error message to indicate what's wrong, but only the whole process exits immediately with these messages:

[+41627 ms] Service protocol connection closed.
[        ] Lost connection to device.
[   +1 ms] DevFS: Deleting filesystem on the device (file:...)

I am not asking about catching the error, as I know these kinds of errors are fatal, I just want some useful logs to see whats happening.

Can I debug the native code somehow or at least get useful error messages about the reason/location of the crash?

HII
  • 3,420
  • 1
  • 14
  • 35
  • 1
    You can check the return code of your process. Beyond that, there's not much to do. There are no mechanisms to get useful error messages because where would they come from? The kernel only knows that something bad happened, it can't debug your code for you. Debug your native code outside of FFI and only bring it into FFI once you know it works. – Christopher Moore Jan 12 '23 at 18:08
  • @ChristopherMoore I am indeed debugging outside ffi(I am running the code first in a normal C app in visual studio) but the same code does not run(crashes the whole process) within ffi but runs in visual studio. The error code is some large negative number, I will check if it has a useful meaning – HII Jan 12 '23 at 19:36
  • @ChristopherMoore if there is a way to attach the visual studio debugger to the C code that is called from dart then this will answer the question as well – HII Jan 12 '23 at 19:38
  • You must be passing a pointer with the wrong level of indirection or something like that from Dart. If you're not having problems using the C code from C, the issue is in your Dart code. You can do print debugging to get an idea of where the issue is in your C code if you don't know already. I don't personally know of a way to attach a debugger to FFI code. – Christopher Moore Jan 12 '23 at 20:08
  • If possible, I would try refactoring it so that you can separately test the interesting parts in a standalone C program with gdb (or your debugger of choice). – jamesdlin Jan 13 '23 at 00:21
  • I'm pretty sure that when you are developing a DLL in Visual Studio, you can specify an arbitrary exe as the 'command line' and it will let you set breakpoints in the DLL code. Your command line would then be `dart some_test_harness.dart` which loads the debug dll and invokes your test methods. – Richard Heap Jan 13 '23 at 14:09
  • @RichardHeap can you suggest an answer with details of how to do that or link me somewhere I can learn more about what you mean? – HII Jan 13 '23 at 15:22

1 Answers1

1

Assumptions: debugging a Windows DLL on Windows using a pure Dart test harness. It should work pretty much the same for a Flutter test harness (i.e. the example app in a Flutter plugin project), but in all likelihood you'll want to do much of the testing in as simple a test environment as you can.

You are going to need two projects: a Visual Studio DLL project and a pure Dart command line. (In what follows my examples are in d:\vcc\Dll2\ and d:\source\testffi2\ respectively. The Dart project has a main function in bin\testffi2.dart.)

For testing I removed the VS C++ DLL project boilerplate and replaced it with:

#include "pch.h"
#include "framework.h"
#include "Dll2.h"

#include <cstdint>

extern "C" __declspec(dllexport) int32_t sum(int32_t a, int32_t b) {
    return a + b;
}

and checked that it compiled OK (in Debug/x64 configuration). This built: D:\vcc\Dll2\x64\Debug\Dll2.dll as expected.

In the Dart project I created a simple test harness to load the DLL and the function and call it.

import 'dart:ffi';
import 'dart:io';

void main() {
  final dll = DynamicLibrary.open('D:\\vcc\\Dll2\\x64\\Debug\\Dll2.dll');
  final sumFunction = dll.lookupFunction<
      Int32 Function(
    Int32 a,
    Int32 b,
  ),
      int Function(
    int a,
    int b,
  )>('sum');

  print(sumFunction(123, 321));

  sleep(Duration(seconds: 5)); // this is just there so that the VCC debug
                               // window doesn't immediately close
}

Running this is the Dart IDE or from the command line does, indeed, print 444 as expected, but doesn't give you an opportunity to debug the C.

Finally, back in the Visual Studio project, change the debugging properties to launch the Dart test harness. Set the exe path to the Dart sdk binary, the command line to the Dart main file, and the working folder to the Dart project folder.

VS debug properties

Finally, set a breakpoint on the return a + b line and click the Local Windows Debugger button. Execution pauses as expected in the Visual Studio debugger and the values of local variables a and b are visible, etc.

Richard Heap
  • 48,344
  • 9
  • 130
  • 112