.NET Core Barcode Reader for Windows, Linux & macOS
.NET Core empowers C# developers to build DotNet applications for Windows, Linux, and macOS using one codebase. In this article, I want to share how to create a cross-platform .NET Core barcode app with Dynamsoft Barcode Reader SDK.
.NET Core Installation
The latest .NET Core does not support the project.json files anymore. Instead, it uses MSBuild/csproj files for project configuration. If you have an old version installed and want to upgrade, you’d better read the article: A mapping between project.json and csproj properties.
C/C++ Barcode Libraries for Windows, Linux, and macOS
Get Dynamsoft C/C++ Barcode libraries.
.NET Core Barcode Reader
Create a new console project:
dotnet new console –o DynamsoftBarcode
The command line will generate two files: DynamsoftBarcode.csproj and Program.cs.
Copy shared libraries to the project root folder. To run the app, you have to copy *.dll, *.so, and *.dylib files to the output directory after building the project. Therefore, create an item group in DynamsoftBarcode.csproj file:
<ItemGroup>
<None Update="DynamsoftBarcodeReader.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="libDynamsoftBarcodeReader.dylib">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="libDynamsoftBarcodeReader.so">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
It is time to write some C# code in Program.cs.
To learn how to interoperate with native libraries, you can read the article - Native Interoperability. The technology used for accessing native structs and functions is called P/Invoke. Use the namespace System.Runtime.InteropServices to import shared libraries and define the corresponding native methods.
[DllImport("DynamsoftBarcodeReader")]
public static extern IntPtr DBR_CreateInstance();
[DllImport("DynamsoftBarcodeReader")]
public static extern void DBR_DestroyInstance(IntPtr hBarcode);
[DllImport("DynamsoftBarcodeReader")]
public static extern int DBR_InitLicense(IntPtr hBarcode, string license);
[DllImport("DynamsoftBarcodeReader")]
public static extern int DBR_DecodeFile(IntPtr hBarcode, string filename, string template);
[DllImport("DynamsoftBarcodeReader")]
public static extern int DBR_FreeTextResults(ref IntPtr pBarcodeResultArray);
[DllImport("DynamsoftBarcodeReader")]
public static extern void DBR_GetAllTextResults(IntPtr hBarcode, ref IntPtr pBarcodeResultArray);
[DllImport("DynamsoftBarcodeReader")]
public static extern int DBR_GetTemplateSettings(IntPtr hBarcode, string pszTemplateName, ref PublicParameterSettings pBarcodeResultArray);
[DllImport("DynamsoftBarcodeReader")]
public static extern int DBR_SetTemplateSettings(IntPtr hBarcode, string pszTemplateName, ref PublicParameterSettings pBarcodeResultArray, char[] szErrorMsgBuffer, int nErrorMsgBufferLen);
Invoking barcode APIs is not a big deal. The critical point is memory management – how to convert the managed structure to an unmanaged pointer and vice versa.
To pass a managed structure to an unmanaged pointer:
LinuxMacBarcodeManager.ReaderOptions ro = new LinuxMacBarcodeManager.ReaderOptions();
ro.llBarcodeFormat = iFormat;
ro.iMaxBarcodesNumPerPage = iMaxCount;
// Copy the struct to unmanaged memory.
IntPtr opt = Marshal.AllocHGlobal(Marshal.SizeOf(ro));
Marshal.StructureToPtr(ro, opt, false);
To get the final results, use Marshal.PtrToStructure:
if (pBarcodeResultArray != IntPtr.Zero)
{
WinBarcodeManager.BarcodeResultArray results = (WinBarcodeManager.BarcodeResultArray)Marshal.PtrToStructure(pBarcodeResultArray, typeof(WinBarcodeManager.BarcodeResultArray));
int count = results.iBarcodeCount;
IntPtr[] barcodes = new IntPtr[count];
Marshal.Copy(results.ppBarcodes, barcodes, 0, count);
for (int i = 0; i < count; i++)
{
WinBarcodeManager.BarcodeResult result = (WinBarcodeManager.BarcodeResult)Marshal.PtrToStructure(barcodes[i], typeof(WinBarcodeManager.BarcodeResult));
Console.WriteLine("Value: " + result.pszBarcodeText);
Console.WriteLine("Format: " + result.pszBarcodeFormatString);
Console.WriteLine("-----------------------------");
}
// Release memory of barcode results
WinBarcodeManager.DBR_FreeTextResults(ref pBarcodeResultArray);
}
That’s it. Try the sample code on Windows, Linux, and macOS.
dotnet restore
dotnet run