Отправка байтовых данных С++ с использованием ffi для флаттера

Я использовал этот код в ссылке это, чтобы сделать снимок экрана с помощью GdiPlus и преобразовать растровое изображение в байты png.

#include <iostream>
#include <fstream>
#include <vector>
#include <Windows.h>
#include <gdiplus.h>

bool save_png_memory(HBITMAP hbitmap, std::vector<BYTE>& data)
{
    Gdiplus::Bitmap bmp(hbitmap, nullptr);

    //write to IStream
    IStream* istream = nullptr;
    if (CreateStreamOnHGlobal(NULL, TRUE, &istream) != 0)
        return false;

    CLSID clsid_png;
    if (CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png)!=0)
        return false;
    Gdiplus::Status status = bmp.Save(istream, &clsid_png);
    if (status != Gdiplus::Status::Ok)
        return false;

    //get memory handle associated with istream
    HGLOBAL hg = NULL;
    if (GetHGlobalFromStream(istream, &hg) != S_OK)
        return 0;

    //copy IStream to buffer
    int bufsize = GlobalSize(hg);
    data.resize(bufsize);

    //lock & unlock memory
    LPVOID pimage = GlobalLock(hg);
    if (!pimage)
        return false;
    memcpy(&data[0], pimage, bufsize);
    GlobalUnlock(hg);

    istream->Release();
    return true;
}

int main()
{
    CoInitialize(NULL);

    ULONG_PTR token;
    Gdiplus::GdiplusStartupInput tmp;
    Gdiplus::GdiplusStartup(&token, &tmp, NULL);

    //take screenshot
    RECT rc;
    GetClientRect(GetDesktopWindow(), &rc);
    auto hdc = GetDC(0);
    auto memdc = CreateCompatibleDC(hdc);
    auto hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
    auto oldbmp = SelectObject(memdc, hbitmap);
    BitBlt(memdc, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY);
    SelectObject(memdc, oldbmp);
    DeleteDC(memdc);
    ReleaseDC(0, hdc);

    //save as png
    std::vector<BYTE> data;
    if(save_png_memory(hbitmap, data))
    {
        //write from memory to file for testing:
        std::ofstream fout("test.png", std::ios::binary);
        fout.write((char*)data.data(), data.size());
    }
    DeleteObject(hbitmap);

    Gdiplus::GdiplusShutdown(token);
    CoUninitialize();

    return 0;
}

Вопрос

  • Как можно подготовить эти байтовые данные (стандартные::векторные данные;), чтобы передать их через dart ffi для работы с ними во флаттере?
  • Пожалуйста, в любом случае возможно будет принято.

Моя самая большая путаница заключается в том, что ffi не имеет соответствующего типа данных байта, так как же мне его использовать?

В пакете package:win32 есть методы для некоторых/всех функций GDI win32: pub.dev/documentation/win32/latest/topics/gdi32-topic.html

Richard Heap 09.04.2022 21:40
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
1
35
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Тип данных, который вы ищете на стороне Dart, — это Pointer<Uint8>, который является указателем на байты без знака. Вы можете передать этот указатель через границу ffi и получить доступ к байтам указателя с любой стороны. Но указатель бесполезен для вас, пока вы не выделите место для хранения (подумайте malloc/free).

Есть два способа выделить память (массив байтов), на которую будет ссылаться указатель. Вы можете либо malloc (и впоследствии free) байты на стороне C, либо malloc.allocate<Uint8>() (и впоследствии malloc.free()) их на стороне Dart.

Затем на стороне C у вас уже есть пример кода в вашем фрагменте для копирования std::vector<BYTE> в буфер указателя:

memcpy(&data[0], the_pointer, bufsize);

копирует bufsize байт из data в буфер, на который указывает указатель. (В качестве альтернативы вы можете просто назначить &data[0] указателю, если вы знаете, что данные не выйдут за пределы области видимости, и вы освободите их после использования).

Когда у вас есть Pointer<Uint8> на стороне Dart, просто вызовите asTypedList, чтобы получить Uint8List, который позволит вам получить доступ к байтам на стороне Dart.

Кроме того, помните, что Dart FFI — это интерфейс C, поэтому, если вы хотите использовать классы C++, вам нужно будет обернуть их методами C. См.: Могу ли я вызвать функцию-конструктор С++ в dart ffi? Эти методы C могут/должны быть в исходных файлах C++, если они помечены extern "C".

Другие вопросы по теме