You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将C# byte[]传递给C语言的char指针?

Solving C# byte[] to C char* Interop for Your cROS Library

Hey there! I’ve dealt with exactly this kind of C#/C interop issue for binary data before, so let’s break down how to solve it reliably—whether you need short-term access or long-term shared memory for your cROS library.

First, a critical note: C# byte is an unsigned 8-bit value, so in your C code, you should use unsigned char* instead of char* to avoid unexpected sign-extension bugs. I’ll structure examples around this safer type match.


Option 1: Short-Term Access with unsafe + fixed (Simplest for Synchronous Calls)

If your cROS library only needs access to the byte array during a synchronous function call (no async processing or long-term storage), use C#’s unsafe context and fixed keyword. This pins the managed array in memory so the GC can’t move it while the C code is using it.

C Library Function Declaration

// cROS.h
void cROS_ShareData(unsigned char* data, size_t dataLength);

C# Implementation

using System.Runtime.InteropServices;

public class CrosInterop
{
    [DllImport("cROS.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern void cROS_ShareData(byte* data, int dataLength);

    public unsafe void ShareByteArray(byte[] byteArray)
    {
        if (byteArray == null || byteArray.Length == 0)
            return;

        // Pin the array in memory to prevent GC movement
        fixed (byte* dataPtr = byteArray)
        {
            cROS_ShareData(dataPtr, byteArray.Length);
        }
        // Array is unpinned here—do NOT let C code hold the pointer beyond this block!
    }
}

Option 2: Temporary Unmanaged Memory (For Longer Synchronous Calls)

If you need to pass the data to C but want to avoid unsafe code, use the Marshal class to copy the managed byte array to unmanaged memory. This is great if you’re working in a context where unsafe isn’t allowed.

C# Implementation

using System.Runtime.InteropServices;

public class CrosInterop
{
    [DllImport("cROS.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern void cROS_ShareData(IntPtr data, int dataLength);

    public void ShareByteArray(byte[] byteArray)
    {
        if (byteArray == null || byteArray.Length == 0)
            return;

        // Allocate unmanaged memory equal to the array size
        IntPtr unmanagedData = Marshal.AllocHGlobal(byteArray.Length);
        try
        {
            // Copy managed byte[] to unmanaged memory
            Marshal.Copy(byteArray, 0, unmanagedData, byteArray.Length);
            
            // Call your cROS library function
            cROS_ShareData(unmanagedData, byteArray.Length);
        }
        finally
        {
            // Always free unmanaged memory to avoid leaks!
            Marshal.FreeHGlobal(unmanagedData);
        }
    }
}

Option 3: Long-Term Shared Memory (For Async/Background Processing)

If your cROS library needs to hold onto the data after the C# function returns (e.g., for async processing or shared state), you can’t use the above methods—they either unpin the array or free the memory immediately. Instead, let the C library manage the memory lifecycle.

C Library Code

// cROS.h
unsigned char* cROS_AllocateData(size_t dataLength);
void cROS_FreeData(unsigned char* data);
void cROS_StoreSharedData(unsigned char* data, size_t dataLength);

// cROS.c
unsigned char* cROS_AllocateData(size_t dataLength)
{
    return (unsigned char*)malloc(dataLength);
}

void cROS_FreeData(unsigned char* data)
{
    free(data);
}

void cROS_StoreSharedData(unsigned char* data, size_t dataLength)
{
    // Store the data pointer for later use (e.g., in a global struct or queue)
}

C# Implementation

using System.Runtime.InteropServices;

public class CrosInterop
{
    [DllImport("cROS.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern IntPtr cROS_AllocateData(int dataLength);

    [DllImport("cROS.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern void cROS_FreeData(IntPtr data);

    [DllImport("cROS.dll", CallingConvention = CallingConvention.Cdecl)]
    private static extern void cROS_StoreSharedData(IntPtr data, int dataLength);

    public void ShareLongLivedByteArray(byte[] byteArray)
    {
        if (byteArray == null || byteArray.Length == 0)
            return;

        // Ask cROS to allocate unmanaged memory
        IntPtr unmanagedData = cROS_AllocateData(byteArray.Length);
        if (unmanagedData == IntPtr.Zero)
            throw new OutOfMemoryException("Failed to allocate memory in cROS library");

        try
        {
            // Copy managed data to the cROS-allocated memory
            Marshal.Copy(byteArray, 0, unmanagedData, byteArray.Length);
            
            // Pass the data to cROS for long-term storage
            cROS_StoreSharedData(unmanagedData, byteArray.Length);
            
            // Do NOT free the memory here—cROS will handle it when done (call cROS_FreeData later)
        }
        catch
        {
            // Clean up if something goes wrong
            cROS_FreeData(unmanagedData);
            throw;
        }
    }
}

Key Best Practices

  • Avoid char* for binary data: Always use unsigned char* in C and byte*/IntPtr in C# to match C#’s unsigned byte type.
  • Memory lifecycle is critical: Never let C code hold a pointer to a managed array outside a fixed block, and always track unmanaged memory to prevent leaks.
  • Calling convention consistency: Make sure CallingConvention in DllImport matches your C library’s convention (most C libraries use Cdecl).

内容的提问来源于stack exchange,提问作者IsmailYC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:08:56