Unity中IntPtr转byte数组:已知C++行列信息时的实现及崩溃问题
Alright, let’s tackle this interop problem between C++ and Unity— I’ve run into similar memory boundary crashes before, so I know exactly where to look. First, let’s confirm the core assumption here: since you mentioned size = rows * cols * 3 works in another project, your C++ uchar* is almost certainly pointing to RGB image data (3 bytes per pixel). That’s the foundation of our solution.
Step 1: Correctly Calculate the Byte Array Size
The math rows * cols * 3 is right for RGB, but we need to make sure the values of rows and cols are valid in C#:
- Ensure the C++ code returns these as signed integers (not unsigned types like
uint), because converting an unsigned value larger thanint.MaxValueto C#intwill result in a negative number— which would maketotalBytesnegative, causing a catastrophic memory access crash. - Add sanity checks for non-positive values (e.g.,
rows <= 0orcols <= 0) before proceeding; invalid dimensions are a common crash trigger.
Step 2: Safe Marshal.Copy Implementation
Here’s how to structure the C# code to avoid boundary errors:
using System.Runtime.InteropServices; using UnityEngine; public class ImageInterop : MonoBehaviour { // Import your C++ functions [DllImport("YourCppLibraryName.dll")] private static extern IntPtr GetImageData(out int rows, out int cols); [DllImport("YourCppLibraryName.dll")] private static extern void FreeImageData(IntPtr data); public byte[] ConvertCppImageToByteArray() { // Get the image pointer and dimensions from C++ IntPtr imagePtr = GetImageData(out int rows, out int cols); // Guard against invalid pointers or dimensions if (imagePtr == IntPtr.Zero) { Debug.LogError("C++ returned a null image pointer!"); return null; } if (rows <= 0 || cols <= 0) { Debug.LogError($"Invalid image dimensions: {rows}x{cols}"); FreeImageData(imagePtr); return null; } // Calculate total bytes and create the array int totalBytes = rows * cols * 3; byte[] imageBytes = new byte[totalBytes]; try { // Copy data from unmanaged memory to managed byte array Marshal.Copy(imagePtr, imageBytes, 0, totalBytes); } catch (System.Exception ex) { Debug.LogError($"Failed to copy image data: {ex.Message}"); FreeImageData(imagePtr); return null; } // Critical: Free the unmanaged memory allocated by C++ FreeImageData(imagePtr); return imageBytes; } }
Why Your Unity Project is Crashing (And How to Fix It)
The crash is almost certainly a memory boundary violation— here are the most likely culprits:
- Invalid Memory Pointer: If your C++ code returns a pointer to stack-allocated memory (instead of heap-allocated with
new[]), the memory gets freed immediately after the C++ function returns. Accessing this in C# causes a crash. Ensure your C++ code uses heap allocation, and provides a dedicated function to free the memory (likeFreeImageDatain the example above). - Mismatched Data Format: If your C++ image is actually RGBA (4 bytes per pixel) instead of RGB,
rows*cols*3will be too small—Marshal.Copywill read past the end of the allocated memory. Double-check the image format in your C++ code. - Row Stride Alignment: Some image libraries add padding bytes to each row to align memory (e.g., to 4-byte boundaries). In this case,
rows*cols*3won’t equal the actual memory size. You’ll need to modify your C++ function to return the row stride (bytes per row) instead of just rows/cols, then calculatetotalBytes = rows * stride. - Type Mismatches: If C++ uses
size_tfor rows/cols, converting that to C#intcan cause overflow on large images. Uselongfor the size calculation if you’re dealing with high-resolution images.
Critical Memory Management Note
Never use Marshal.FreeHGlobal to free memory allocated by C++ with new[]— this will cause memory corruption. Always use a C++-exported function to free the memory, as shown in the example.
内容的提问来源于stack exchange,提问作者Dilara Albayrak

