千家信息网

怎么使用C++实现Flutter Windows插件

发表于:2024-11-16 作者:千家信息网编辑
千家信息网最后更新 2024年11月16日,这篇文章主要介绍"怎么使用C++实现Flutter Windows插件",在日常操作中,相信很多人在怎么使用C++实现Flutter Windows插件问题上存在疑惑,小编查阅了各式资料,整理出简单好
千家信息网最后更新 2024年11月16日怎么使用C++实现Flutter Windows插件

这篇文章主要介绍"怎么使用C++实现Flutter Windows插件",在日常操作中,相信很多人在怎么使用C++实现Flutter Windows插件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答"怎么使用C++实现Flutter Windows插件"的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

如何把C++条形码SDK集成到Flutter Windows插件中

Flutter创建的Windows插件工程目录结构如下:

bin  /DynamsoftBarcodeReaderx64.dllinclude  /flutter_barcode_sdk    /flutter_barcode_sdk_plugin.h  /barcode_manager.h  /DynamsoftBarcodeReader.h  /DynamsoftCommon.hlib  /DBRx64.libCMakeLists.txtflutter_barcode_sdk_plugin.cpp
  • CMakeLists.txt是CMake的配置文件。

  • flutter_barcode_sdk_plugin.cpp用于实现插件的C++代码逻辑。

  • DynamsoftBarcodeReaderx64.dllDBRx64.libDynamsoftBarcodeReader.h,以及DynamsoftCommon.h可以从C++ SDK中获取。

  • 为了方便,条形码接口调用的实现都放在barcode_manager.h中。

从Dart传到C++的接口和参数,会在HandleMethodCall()中解析:

void FlutterBarcodeSdkPlugin::HandleMethodCall(      const flutter::MethodCall &method_call,      std::unique_ptr> result)  {    const auto *arguments = std::get_if(method_call.arguments());    if (method_call.method_name().compare("getPlatformVersion") == 0)    {          }    else if (method_call.method_name().compare("setLicense") == 0)    {          }    else if (method_call.method_name().compare("decodeFile") == 0)    {          }    else if (method_call.method_name().compare("decodeFileBytes") == 0)    {          }    else if (method_call.method_name().compare("decodeImageBuffer") == 0)    {          }    else    {      result->NotImplemented();    }  }}

获取参数,并转换成C++类型:stringintvector

std::string filename;auto filename_it = arguments->find(EncodableValue("filename"));if (filename_it != arguments->end()){  filename = std::get(filename_it->second);}std::vector bytes;auto bytes_it = arguments->find(EncodableValue("bytes"));if (bytes_it != arguments->end()){  bytes = std::get>(bytes_it->second);}int width = 0;auto width_it = arguments->find(EncodableValue("width"));if (width_it != arguments->end()){  width = std::get(width_it->second);}

返回的结果需要封装成Flutter定义的类型:

EncodableList results;result->Success(results);

接下来在barcode_manager.h中实现解码和结果封装。

这里定义三个解码接口:

EncodableList DecodeFile(const char * filename) {    EncodableList out;       int ret = reader->DecodeFile(filename, "");    if (ret == DBRERR_FILE_NOT_FOUND)    {        printf("Error code %d. %s\n", ret, CBarcodeReader::GetErrorString(ret));        return out;    }    return WrapResults();}EncodableList DecodeFileBytes(const unsigned char * bytes, int size) {    reader->DecodeFileInMemory(bytes, size, "");    return WrapResults();}EncodableList DecodeImageBuffer(const unsigned char * buffer, int width, int height, int stride, int format) {    ImagePixelFormat pixelFormat = IPF_BGR_888;    switch(format) {        case 0:            pixelFormat = IPF_GRAYSCALED;            break;        case 1:            pixelFormat = IPF_ARGB_8888;            break;    }    reader->DecodeBuffer(buffer, width, height, stride, pixelFormat, "");    return WrapResults();}

获取解码结果,并封装到Flutter的maplist中:

EncodableList WrapResults() {    EncodableList out;    TextResultArray *results = NULL;    reader->GetAllTextResults(&results);            if (results->resultsCount == 0)    {        printf("No barcode found.\n");        CBarcodeReader::FreeTextResults(&results);    }        for (int index = 0; index < results->resultsCount; index++)    {        EncodableMap map;        map[EncodableValue("format")] = results->results[index]->barcodeFormatString;        map[EncodableValue("text")] = results->results[index]->barcodeText;        map[EncodableValue("x1")] = results->results[index]->localizationResult->x1;        map[EncodableValue("y1")] = results->results[index]->localizationResult->y1;        map[EncodableValue("x2")] = results->results[index]->localizationResult->x2;        map[EncodableValue("y2")] = results->results[index]->localizationResult->y2;        map[EncodableValue("x3")] = results->results[index]->localizationResult->x3;        map[EncodableValue("y3")] = results->results[index]->localizationResult->y3;        map[EncodableValue("x4")] = results->results[index]->localizationResult->x4;        map[EncodableValue("y4")] = results->results[index]->localizationResult->y4;        out.push_back(map);    }    CBarcodeReader::FreeTextResults(&results);    return out;}

到此,用于Windows插件的C++代码已经完成。最后一步就是配置CMakeLists.txt文件。

链接C++库:

link_directories("${PROJECT_SOURCE_DIR}/lib/") target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin "DBRx64")

打包动态链接库:

set(flutter_barcode_sdk_bundled_libraries  "${PROJECT_SOURCE_DIR}/bin/"  PARENT_SCOPE)

这步很重要。如果没有打包进去,应用程序会因为缺少DLL无法运行。

用Flutter实现Windows桌面条码识别程序

有了插件就可以快速实现桌面扫码应用。

创建一个新工程,并在pubspec.yaml中添加依赖:

dependencies:  flutter:    sdk: flutter  flutter_barcode_sdk:

创建SDK对象:

class _DesktopState extends State {  String _platformVersion = 'Unknown';  final _controller = TextEditingController();  String _barcodeResults = '';  FlutterBarcodeSdk _barcodeReader;  bool _isValid = false;  String _file = '';  @override  void initState() {    super.initState();    initPlatformState();    initBarcodeSDK();  }  Future initBarcodeSDK() async {    _barcodeReader = FlutterBarcodeSdk();    // Get 30-day FREEE trial license from https://www.dynamsoft.com/customer/license/trialLicense?product=dbr    await _barcodeReader.setLicense('LICENSE-KEY');  }}

使用TextFieldImageMaterialButtonText构建UI:

@overrideWidget build(BuildContext context) {  return MaterialApp(    home: Scaffold(        appBar: AppBar(          title: const Text('Dynamsoft Barcode Reader'),        ),        body: Column(children: [          Container(            height: 100,            child: Row(children: [              Text(                _platformVersion,                style: TextStyle(fontSize: 14, color: Colors.black),              )            ]),          ),          TextField(            controller: _controller,            decoration: InputDecoration(              labelText: 'Input an image path',              errorText: _isValid ? null : 'File not exists',            ),          ),          Expanded(            child: SingleChildScrollView(              child: Column(                children: [                  getDefaultImage(),                  Text(                    _barcodeResults,                    style: TextStyle(fontSize: 14, color: Colors.black),                  ),                ],              ),            ),          ),          Container(            height: 100,            child: Row(                mainAxisAlignment: MainAxisAlignment.spaceEvenly,                children: [                  MaterialButton(                      child: Text('Decode Barcode'),                      textColor: Colors.white,                      color: Colors.blue,                      onPressed: () async {                        if (_controller.text.isEmpty) {                          setState(() {                            _isValid = false;                            _barcodeResults = '';                            _file = '';                          });                          return;                        }                        File file = File(_controller.text);                        if (!file.existsSync()) {                          setState(() {                            _isValid = false;                            _barcodeResults = '';                            _file = '';                          });                          return;                        } else {                          setState(() {                            _isValid = true;                            _file = _controller.text;                          });                        }                        Uint8List bytes = await file.readAsBytes();                        List results =                            await _barcodeReader.decodeFileBytes(bytes);                        setState(() {                          _barcodeResults = getBarcodeResults(results);                        });                      }),                ]),          ),        ])),  );}

图片默认显示资源包中的图。如果输入的图片有效,显示输入的图片:

Widget getDefaultImage() {  if (_controller.text.isEmpty || !_isValid) {    return Image.asset('images/default.png');  } else {    return Image.file(File(_file));  }}

要使用资源图片,需要在pubspec.yaml中添加:

flutter:  assets:    - images/default.png

最后运行程序:

flutter run -d windows

到此,关于"怎么使用C++实现Flutter Windows插件"的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

0