C#中如何将LeadTools返回的非托管指针封送为BARCODEDATA对象数组?
Got it, let's work through how to convert that unmanaged pointer from LeadTools' L_BarCodeRead into a full array of BARCODEDATA instances when reading all barcodes. Your initial approach with a fixed-size BarCodeArray won't work because the number of barcodes is dynamic—here's the right way to handle it:
Step 1: Get the total number of barcodes first
When you set the parameter to read all barcodes, the first element in the unmanaged array already tells you how many barcodes were found via the nTotalCount field. Start by marshaling that first instance to get the count:
if (LeadTools13Imports.SUCCESS == retVal) { // First, get the first BARCODEDATA to retrieve the total count var firstBarcode = (LeadTools13Imports.BARCODEDATA)Marshal.PtrToStructure( pBarcodesRaw, typeof(LeadTools13Imports.BARCODEDATA) ); int totalBarcodes = firstBarcode.nTotalCount; if (totalBarcodes <= 0) { // No barcodes found, handle accordingly return; }
Step 2: Marshal each barcode in the array
Next, calculate the size of a single BARCODEDATA structure, then loop through each offset in the unmanaged memory block to marshal each instance individually:
// Calculate the size of one BARCODEDATA structure int barcodeSize = Marshal.SizeOf(typeof(LeadTools13Imports.BARCODEDATA)); var barcodeDataArray = new LeadTools13Imports.BARCODEDATA[totalBarcodes]; for (int i = 0; i < totalBarcodes; i++) { // Calculate the pointer to the i-th BARCODEDATA in the array IntPtr currentBarcodePtr = IntPtr.Add(pBarcodesRaw, i * barcodeSize); // Marshal the structure from unmanaged memory barcodeDataArray[i] = (LeadTools13Imports.BARCODEDATA)Marshal.PtrToStructure( currentBarcodePtr, typeof(LeadTools13Imports.BARCODEDATA) ); } // Now barcodeDataArray contains all your scanned barcodes }
Step 3: Don't forget to clean up unmanaged memory
LeadTools allocates memory for that barcode array, so you must free it using their API to avoid memory leaks. After you're done using the array, call:
LeadTools13Imports.L_BarCodeFree(pBarcodesRaw);
Why your initial BarCodeArray didn't work
The [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] attribute requires a fixed, compile-time size for the array. Since the number of barcodes varies per image, this approach can't adapt to dynamic counts. The loop-based method above handles any number of barcodes by using the nTotalCount from the first structure to drive the iteration.
Key Notes
- The
BARCODEDATAclass is marked with[StructLayout(LayoutKind.Sequential)], which matches the unmanaged memory layout—this is critical for correct marshaling. - The
pszBarCodeDatastring is marshaled automatically via[MarshalAs(UnmanagedType.LPStr)], so you don't need to handle that memory separately (LeadTools will free it when you callL_BarCodeFree).
内容的提问来源于stack exchange,提问作者Crozetian

