这篇文章主要介绍“如何使用C++实现Flutter Windows插件”,在日常操作中,相信很多人在如何使用C++实现Flutter Windows插件问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用C++实现Flutter Windows插件”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
上周实现的Flutter条形码插件已经发布到https://pub.dev/packages/flutter_barcode_sdk,平台相关部分只包含了Android的Java代码。这周新增用于Windows的C++代码。后续计划还包含iOS和Web。
安装包下载:https://www.dynamsoft.com/barcode-reader/downloads
30天试用序列号:https://www.dynamsoft.com/customer/license/trialLicense/?product=dbr
Flutter桌面插件开发的资源比较少。可以从以下三个入手:
https://flutter.dev/desktop
https://github.com/google/flutter-desktop-embedding
https://github.com/flutter/samples/tree/master/experimental/desktop_photo_search
Flutter创建的Windows插件工程目录结构如下:
bin /DynamsoftBarcodeReaderx64.dll include /flutter_barcode_sdk /flutter_barcode_sdk_plugin.h /barcode_manager.h /DynamsoftBarcodeReader.h /DynamsoftCommon.h lib /DBRx64.lib CMakeLists.txt flutter_barcode_sdk_plugin.cpp
CMakeLists.txt
是CMake的配置文件。
flutter_barcode_sdk_plugin.cpp
用于实现插件的C++代码逻辑。
DynamsoftBarcodeReaderx64.dll
,DBRx64.lib
,DynamsoftBarcodeReader.h
,以及DynamsoftCommon.h
可以从C++ SDK中获取。
为了方便,条形码接口调用的实现都放在barcode_manager.h
中。
从Dart传到C++的接口和参数,会在HandleMethodCall()
中解析:
void FlutterBarcodeSdkPlugin::HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &method_call,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result)
{
const auto *arguments = std::get_if<EncodableMap>(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++类型:string
,int
,vector<unsigned char>
:
std::string filename;
auto filename_it = arguments->find(EncodableValue("filename"));
if (filename_it != arguments->end())
{
filename = std::get<std::string>(filename_it->second);
}
std::vector<unsigned char> bytes;
auto bytes_it = arguments->find(EncodableValue("bytes"));
if (bytes_it != arguments->end())
{
bytes = std::get<vector<unsigned char>>(bytes_it->second);
}
int width = 0;
auto width_it = arguments->find(EncodableValue("width"));
if (width_it != arguments->end())
{
width = std::get<int>(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的map
和list
中:
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无法运行。
有了插件就可以快速实现桌面扫码应用。
创建一个新工程,并在pubspec.yaml
中添加依赖:
dependencies:
flutter:
sdk: flutter
flutter_barcode_sdk:
创建SDK对象:
class _DesktopState extends State<Desktop> {
String _platformVersion = 'Unknown';
final _controller = TextEditingController();
String _barcodeResults = '';
FlutterBarcodeSdk _barcodeReader;
bool _isValid = false;
String _file = '';
@override
void initState() {
super.initState();
initPlatformState();
initBarcodeSDK();
}
Future<void> 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');
}
}
使用TextField
,Image
,MaterialButton
和Text
构建UI:
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Dynamsoft Barcode Reader'),
),
body: Column(children: [
Container(
height: 100,
child: Row(children: <Widget>[
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: <Widget>[
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<BarcodeResult> 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
https://github.com/yushulx/flutter_barcode_sdk
到此,关于“如何使用C++实现Flutter Windows插件”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/yushulx/blog/5036621