Windows Universal App中集成C/C++ DLL

藉助Windows 10的普及,微軟開始推Universal應用開發。Universal應用其實和Android和iOS應用同樣,運行在sandbox中,在桌面環境裏exe不能雙擊運行。打成一個appx包以後能夠提交到Windows Store。任何運行Windows 10的設備均可以運行。那麼在開發的時候,現有的C/C++ SDK是否能夠兼容呢?答案是能夠的,不過會有一些限制。若是你想讓SDK兼容全部的設備,須要提供行x86, x64, arm三個版本DLL。我用Dynamsoft Barcode SDK作了試驗。html

參考原文:How to Create a Universal Barcode Reader on Windows 10 with C/C++ Legacy Codegit

做者:Xiao Linggithub

翻譯:yushulxwindows

準備工做

Hello World

編寫Hello World很簡單,能夠學習微軟的在線教程https://msdn.microsoft.com/en-us/library/windows/apps/dn996906.aspx
spa

在Universal App中集成C/C++ SDK

建立一個Universal應用。
翻譯

 MainPage.xaml中添加ImageButtonTextBlock
指針

<ScrollViewer Grid.Row="1" VerticalScrollMode="Auto" VerticalScrollBarVisibility="Auto" VerticalAlignment="Top">
                <StackPanel>
                    <Grid x:Name="Image" Margin="0,0,0,5" VerticalAlignment="Top">
                        <Image x:Name="PreviewImage" HorizontalAlignment="Left" VerticalAlignment="Top" MaxWidth="600"/>
                    </Grid>
                    <StackPanel Orientation="Horizontal" Margin="0, 0, 0, 5" VerticalAlignment="Top">
                        <Button x:Name="button" Margin="0, 0, 5, 0" Click="button_Click" VerticalAlignment="Top">
                            <Viewbox MaxHeight="40" MaxWidth="40">
                                <SymbolIcon Symbol="OpenFile"/>
                            </Viewbox>
                        </Button>
                        <TextBlock x:Name="BarcodeResults" Margin="0,0,0,10" TextWrapping="Wrap" Text="Results:" Height="600" Width="300" VerticalAlignment="Stretch" HorizontalAlignment="Left" />
                    </StackPanel>
                </StackPanel>
            </ScrollViewer>
 

使用FileOpenPicker來加載文件:

FileOpenPicker^ picker = ref new FileOpenPicker();
picker->FileTypeFilter->Append(".bmp");
picker->SuggestedStartLocation = PickerLocationId::PicturesLibrary;
 

WriteableBitmap中獲取圖像數據的C++指針:

byte* GetPointerToPixelData(IBuffer^ pixelBuffer, unsigned int *length)
{
    if (length != nullptr)
    {
        *length = pixelBuffer->Length;
    }
    // Query the IBufferByteAccess interface.
    ComPtr<IBufferByteAccess> bufferByteAccess;
    reinterpret_cast<IInspectable*>(pixelBuffer)->QueryInterface(IID_PPV_ARGS(&bufferByteAccess));
 
    // Retrieve the buffer data.
    byte* pixels = nullptr;
    bufferByteAccess->Buffer(&pixels);
    return pixels;
}
 

使用DecodeBuffer檢測圖像數據。由於沒有對應的接口,須要本身構造數據 (BITMAPINFOHEADER + Image data)。BITMAPINFOHEADER爲40個字節,再加上實際的數據:

char *total = (char *)malloc(len + 40);
BITMAPINFOHEADER bitmap_info = { 40, width, height, 0, 32, 0, len, 0, 0, 0, 0 };
memcpy(total, &bitmap_info, 40);
char *data = total + 40;
memcpy(data, buffer, len);
 

獲取barcode結果:

iRet = reader.DecodeBuffer((unsigned char*)total, len + 40);
 
    // Output barcode result
    pszTemp = (char*)malloc(4096);
    if (iRet != DBR_OK)
    {
        sprintf(pszTemp, "Failed to read barcode: %s\r\n", DBR_GetErrorString(iRet));
        free(pszTemp);
        return nullptr;
    }
 
    pBarcodeResultArray paryResult = NULL;
    reader.GetBarcodes(&paryResult);
 

接下來就是要想辦法把C String轉換成Platform::String^StackOverflow上能夠找到解答:

results = ref new Array<String^>(paryResult->iBarcodeCount);
    for (iIndex = 0; iIndex < paryResult->iBarcodeCount; iIndex++)
    {
        sprintf(pszTemp, "Barcode %d:\r\n", iIndex + 1);
        sprintf(pszTemp, "%s    Page: %d\r\n", pszTemp, paryResult->ppBarcodes[iIndex]->iPageNum);
        sprintf(pszTemp, "%s    Type: %s\r\n", pszTemp, GetFormatStr(paryResult->ppBarcodes[iIndex]->llFormat));
        pszTemp1 = (char*)malloc(paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
        memset(pszTemp1, 0, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength + 1);
        memcpy(pszTemp1, paryResult->ppBarcodes[iIndex]->pBarcodeData, paryResult->ppBarcodes[iIndex]->iBarcodeDataLength);
        sprintf(pszTemp, "%s    Value: %s\r\n", pszTemp, pszTemp1);
 
        // http://stackoverflow.com/questions/11545951/how-to-convert-from-char-to-platformstring-c-cli
        std::string s_str = std::string(pszTemp);
        std::wstring wid_str = std::wstring(s_str.begin(), s_str.end());
        const wchar_t* w_char = wid_str.c_str();
        OutputDebugString(w_char);
        barcode_result = ref new String(w_char);
        results->set(iIndex, barcode_result);
        free(pszTemp1);
    }

<Dynamsoft Barcode SDK>\Redist\C_C++目錄拷貝DynamsoftBarcodeReaderx86.dllDynamsoftBarcodeReader\Debug\DynamsoftBarcodeReader\AppX目錄。

如今能夠經過CTRL+F5或者菜單來運行程序了。

Universal Barcode Reader 截圖:

已知問題

  • 開發Universal應用的時候,有些C的接口是受到限制的,所以SDK中提供的DecodeFile接口用不了,由於須要調用fopen。具體限制能夠參考CRT functions not supported in Universal Windows Platform apps

  • SDK中提供的QR二維碼解碼失效。

  • DecodeBuffer的時候只能使用BMP圖像。

源碼

https://github.com/dynamsoftsamples/universal-windows-barcode-reader

相關文章
相關標籤/搜索