DEV Community

Xiao Ling
Xiao Ling

Posted on • Originally published at dynamsoft.com

How to Build .NET 6 Barcode and QR Code SDK for Windows, Linux & macOS

Microsoft .NET 6 SDK empowers C# developers to build cross-platform DotNet applications for Windows, Linux, and macOS from one codebase. This article describes the steps to build a .NET 6 barcode and QR code decoding library based on Dynamsoft C/C++ Barcode SDK, as well as how to pack the library into a NuGet package.

.NET 6 SDK Installation

Dynamsoft Barcode Reader

  1. Download C/C++ SDK v9.0.
  2. Get a valid license key for activating the SDK.

Steps to Develop and Build .NET 6 Barcode and QR Code SDK

  1. Create a new library project:

    dotnet new classlib -o BarcodeQRCodeSDK 
  2. Copy shared library files from the C/C++ SDK package to the project root directory. For different platforms, the minimum required shared library files are:

- Windows: `DynamsoftBarcodeReader.dll`, `vcomp110.dll` - Linux: `libDynamsoftBarcodeReader.so` - macOS: `libDynamsoftBarcodeReader.dylib` 
Enter fullscreen mode Exit fullscreen mode
  1. Rename Class1.cs to BarcodeQRCodeReader.cs.
  2. P/Invoke is the technology used for bridging C/C++ and .NET. In the BarcodeQRCodeReader.cs file, we use DllImport to load the unmanaged shared library (e.g. *.dll, *.so, *.dylib) and define some managed methods to communicate with the native component.

    [DllImport("DynamsoftBarcodeReader")] static extern IntPtr DBR_CreateInstance(); [DllImport("DynamsoftBarcodeReader")] static extern void DBR_DestroyInstance(IntPtr hBarcode); [DllImport("DynamsoftBarcodeReader")] static extern int DBR_InitLicense(string license, [Out] byte[] errorMsg, int errorMsgSize); [DllImport("DynamsoftBarcodeReader")] static extern int DBR_DecodeFile(IntPtr hBarcode, string filename, string template); [DllImport("DynamsoftBarcodeReader")] static extern int DBR_FreeTextResults(ref IntPtr pTextResultArray); [DllImport("DynamsoftBarcodeReader")] static extern void DBR_GetAllTextResults(IntPtr hBarcode, ref IntPtr pTextResultArray); [DllImport("DynamsoftBarcodeReader")] static extern int DBR_DecodeBuffer(IntPtr hBarcode, IntPtr pBufferBytes, int width, int height, int stride, ImagePixelFormat format, string template); [DllImport("DynamsoftBarcodeReader")] static extern int DBR_DecodeBase64String(IntPtr hBarcode, string base64string, string template); 
  3. In addition, we need to define some native structs in C#:

    [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct PTextResult { BarcodeFormat emBarcodeFormat; public string barcodeFormatString; BarcodeFormat_2 barcodeFormat_2; string barcodeFormatString_2; public string barcodeText; IntPtr barcodeBytes; int barcodeBytesLength; IntPtr localizationResult; IntPtr detailedResult; int resultsCount; IntPtr results; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 56)] char[] reserved; } [StructLayout(LayoutKind.Sequential, Pack = 1)] internal struct TextResultArray { public int resultsCount; public IntPtr results; } 
  4. The memory operation between the managed structure and the unmanaged pointer is a little bit tricky. We need to use Marshal to convert data:

    IntPtr pTextResultArray = IntPtr.Zero; DBR_GetAllTextResults(hBarcode, ref pTextResultArray); if (pTextResultArray != IntPtr.Zero) { string[]? resultArray = null; TextResultArray? results = (TextResultArray?)Marshal.PtrToStructure(pTextResultArray, typeof(TextResultArray)); if (results != null) { int count = results.Value.resultsCount; if (count > 0) { IntPtr[] barcodes = new IntPtr[count]; Marshal.Copy(results.Value.results, barcodes, 0, count); resultArray = new string[count]; for (int i = 0; i < count; i++) { PTextResult? result = (PTextResult?)Marshal.PtrToStructure(barcodes[i], typeof(PTextResult)); if (result != null) { resultArray[i] = result.Value.barcodeText; } } } } DBR_FreeTextResults(ref pTextResultArray); return resultArray; } 
  5. Once the communication problem between managed and unmanaged code is solved, we can define some high-level C# methods:

    public class BarcodeQRCodeReader { private IntPtr hBarcode; private static string? licenseKey; public static void InitLicense(string license) { byte[] errorMsg = new byte[512]; licenseKey = license; DBR_InitLicense(license, errorMsg, 512); Console.WriteLine(Encoding.ASCII.GetString(errorMsg) + "\n"); } private BarcodeQRCodeReader() { hBarcode = DBR_CreateInstance(); } public static BarcodeQRCodeReader Create() { if (licenseKey == null) { throw new Exception("Please call InitLicense first."); } return new BarcodeQRCodeReader(); } ~BarcodeQRCodeReader() { if (hBarcode != IntPtr.Zero) { DBR_DestroyInstance(hBarcode); hBarcode = IntPtr.Zero; } } public void Destroy() { if (hBarcode != IntPtr.Zero) { DBR_DestroyInstance(hBarcode); hBarcode = IntPtr.Zero; } } public string[]? DecodeFile(string filename) { if (hBarcode == IntPtr.Zero) return null; int ret = DBR_DecodeFile(hBarcode, filename, ""); return OutputResults(); } } 
  6. Build the source code to generate the *.dll file.

    dotnet build --configuration Release 

How to Generate and Publish NuGet Package

To generate the *.nupkg file, the easiest way is to add <GeneratePackageOnBuild>true</GeneratePackageOnBuild> to the *.csproj file:

<PropertyGroup> ... <GeneratePackageOnBuild>true</GeneratePackageOnBuild> ... </PropertyGroup> 
Enter fullscreen mode Exit fullscreen mode

Then the *.nupkg file will be generated automatically when you build the project.

Our package contains some native library files. To pack them into the *.nupkg file correctly, we set the corresponding PackagePath in *.csproj file according to the Runtime Identifier:

<ItemGroup> <None CopyToOutputDirectory="Always" Include="DynamsoftBarcodeReader.dll" Pack="true" PackagePath="runtimes/win-x64/native/DynamsoftBarcodeReader.dll" /> <None CopyToOutputDirectory="Always" Include="vcomp110.dll" Pack="true" PackagePath="runtimes/win-x64/native/vcomp110.dll" /> <None CopyToOutputDirectory="Always" Include="libDynamsoftBarcodeReader.dylib" Pack="true" PackagePath="runtimes/osx-x64/native/libDynamsoftBarcodeReader.dylib" /> <None CopyToOutputDirectory="Always" Include="libDynamsoftBarcodeReader.so" Pack="true" PackagePath="runtimes/linux-x64/native/libDynamsoftBarcodeReader.so" /> </ItemGroup> 
Enter fullscreen mode Exit fullscreen mode

As the *.nupkg file is ready, we can publish it to the NuGet Gallery either via the dotnet command:

dotnet nuget push *.nupkg -k <api-key> -s https://api.nuget.org/v3/index.json 
Enter fullscreen mode Exit fullscreen mode

or the NuGet online page.

nuget package upload

Here is the final page of BarcodeQRCodeSDK:
https://www.nuget.org/packages/BarcodeQRCodeSDK/

How to Add a .NET Library Project as a Reference Locally

For source code, add <ProjectReference> in *.csproj file:

<ItemGroup> <ProjectReference Include="..\..\BarcodeQRCodeSDK.csproj" /> </ItemGroup> 
Enter fullscreen mode Exit fullscreen mode

For generated *.nupkg file, add the package directory to NuGet source list and then install the package via dotnet add package:

dotnet nuget add source <package directory> dotnet add package <package name> 
Enter fullscreen mode Exit fullscreen mode

A Simple .NET 6 Command-line Example

  1. Create a new .NET console app:

    dotnet new console -o Test 
  2. Install the .NET Barcode and QR Code SDK:

    dotnet add package BarcodeQRCodeSDK 
  3. Use the following code to decode barcode and QR code from an image file:

    using System; using System.Runtime.InteropServices; using Dynamsoft; namespace Test { class Program { static void Main(string[] args) { BarcodeQRCodeReader.InitLicense("LICENSE-KEY"); BarcodeQRCodeReader? reader = null; try { reader = BarcodeQRCodeReader.Create(); Console.WriteLine("Please enter an image file: "); string? filename = Console.ReadLine(); if (filename != null) { string[]? results = reader.DecodeFile(filename); if (results != null) { foreach (string result in results) { Console.WriteLine(result); } } else { Console.WriteLine("No barcode found."); } } } catch (Exception e) { Console.WriteLine(e.Message); } finally { if (reader != null) { reader.Destroy(); } } } } } 
  4. Run the application in Windows, Linux or macOS:

    dotnet run 

    command-line .NET barcode and QR code reader

Source Code

https://github.com/yushulx/dotnet-barcode-qr-code-sdk

Top comments (0)