使用 MATLAB 进行 Dart FFI

问题描述 投票:0回答:1

我正在尝试让 flutter 应用程序从 .mat 文件中读取 1xN 矩阵,然后使用独立的 matlab 应用程序处理这些数据,因此当我尝试实现应用程序在某个时刻失去连接时

MATLAB 函数:

function results = singleRVAnalysis(sample, numBins)
    % SINGLE_RVANALYSIS Analyzes a single random variable sample
    %
    % Inputs:
    %   sample - Array of sample data
    %   numBins - Number of bins for histogram (default: 50)
    %
    % Outputs:
    %   results - A structure containing PDF, CDF, mean, variance, and third moment

    if nargin < 2
        numBins = 50; 
    end

    edges = linspace(min(sample), max(sample), numBins + 1);

    counts = histcounts(sample, edges);
    binWidth = diff(edges);
    pdf = counts / (sum(counts) * binWidth(1)); 
    cdf = cumsum(pdf) * binWidth(1); 

    binCenters = edges(1:end-1) + diff(edges) / 2;
    meanValue = sum(binCenters .* pdf * binWidth(1));
    varianceValue = sum(((binCenters - meanValue).^2) .* pdf * binWidth(1));
    thirdMomentValue = sum(((binCenters - meanValue).^3) .* pdf * binWidth(1));

    results = struct;
    results.PDF = pdf;
    results.CDF = cdf;
    results.Mean = meanValue;
    results.Variance = varianceValue;
    results.ThirdMoment = thirdMomentValue;
    results.Edges = edges;
end

颤振代码:

import 'dart:ffi';
import 'dart:io';
import 'package:ffi/ffi.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:file_picker/file_picker.dart';

const String dllPath = 'lib\\SingleRVAnalysis\\SingleRVAnalysisLib.dll';

final DynamicLibrary singleRVAnalysisLib = DynamicLibrary.open(dllPath);

final class Results extends Struct {
  external Pointer<Double> pdf;
  external Pointer<Double> cdf;
  @Double()
  external double mean;
  @Double()
  external double variance;
  @Double()
  external double thirdMoment;
  external Pointer<Double> edges;
  @Int32()
  external int binCount;
}

typedef SingleRVAnalysisNative = Results Function(
    Pointer<Double>, Int32, Int32);
typedef SingleRVAnalysisDart = Results Function(Pointer<Double>, int, int);

final singleRVAnalysis = singleRVAnalysisLib.lookupFunction<
    SingleRVAnalysisNative, SingleRVAnalysisDart>('mlxSingleRVAnalysis');

enum FileProcessStatus { idle, processing, completed, failed }

class FileProcessCubit extends Cubit<Map<String, dynamic>> {
  FileProcessCubit() : super({'status': FileProcessStatus.idle, 'file': null});

  void pickFile() async {
    try {
      final result = await FilePicker.platform.pickFiles();

      if (result != null && result.files.single.path != null) {
        emit({
          'status': FileProcessStatus.processing,
          'file': result.files.single,
        });
        await processFile(result.files.single);
      } else {
        emit({
          'status': FileProcessStatus.failed,
          'error': 'No file selected',
        });
      }
    } catch (e) {
      emit({
        'status': FileProcessStatus.failed,
        'error': 'File picking error: $e',
      });
    }
  }

  Future<void> processFile(PlatformFile file) async {
    final filePath = file.path;

    if (filePath == null) {
      emit({
        'status': FileProcessStatus.failed,
        'error': 'No file path available',
      });
      return;
    }

    try {
      final content = await File(filePath).readAsBytes();

      if (content.isEmpty) {
        throw Exception('The file is empty.');
      }

      final List<double> sample = content
          .toString()
          .replaceAll(RegExp(r'[^\d\.\-eE, ]'), '')
          .split(RegExp(r'[,\s]+'))
          .where((e) => e.isNotEmpty)
          .map((e) => double.tryParse(e) ?? 0.0)
          .toList();

      if (sample.isEmpty) {
        throw Exception('Sample array is empty.');
      }

      const int numBins = 50;
      final Pointer<Double> samplePointer = listToPointerDouble(sample);
      final result = singleRVAnalysis(samplePointer, sample.length, numBins);

      try {
        final pdf = result.pdf.asTypedList(numBins).toList();
        final cdf = result.cdf.asTypedList(numBins).toList();
        final mean = result.mean;
        final variance = result.variance;
        final thirdMoment = result.thirdMoment;

        emit({
          'status': FileProcessStatus.completed,
          'mean': mean,
          'variance': variance,
          'thirdMoment': thirdMoment,
          'pdf': pdf,
          'cdf': cdf,
        });
      } catch (e) {
        emit({
          'status': FileProcessStatus.failed,
          'error': 'Error during DLL processing: $e',
        });
      } finally {
        calloc.free(samplePointer);
      }
    } catch (e) {
      emit({
        'status': FileProcessStatus.failed,
        'error': 'Processing failed: $e',
      });
    }
  }

  void reset() {
    emit({'status': FileProcessStatus.idle, 'file': null});
  }
}

Pointer<Double> listToPointerDouble(List<double> sample) {
  final Pointer<Double> pointer =
      calloc.allocate<Double>(sample.length, alignment: 8);

  for (int i = 0; i < sample.length; i++) {
    pointer[i] = sample[i];
  }

  return pointer;
}

它应该分配样本指针,然后将其传递给函数以返回结果,但它在分配样本指针时的某个时刻崩溃了

flutter matlab ffi
1个回答
0
投票

尝试像这样修改你的 dart 代码:

Pointer<Double> listToPointerDouble(List<double> sample) {
  final Pointer<Double> pointer =
      calloc.allocate<Double>(sample.length, alignment: 8);
  final nativeSamples = pointer.asTypedList(sample.length);
  nativeSamples.setAll(0, sample);
  return pointer.cast<Double>();
}

不要忘记在不需要后释放你的内存。

calloc.free(pointer);
© www.soinside.com 2019 - 2024. All rights reserved.