Search code examples
c#c++.netinteropmanaged

Avoiding string allocations on native-to-managed callbacks


I have a native library which passes hardware data to managed code via callbacks.
The basic native-to-managed plumbing is done by

[DllImport("Library.dll")]
public static extern bool Init(IntPtr dataCallBack)

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void Data(string data);

...

var handler = Marshal.GetFunctionPointerForDelegate(HandleData);
Init(handler);

...

private static void HandleData(string data)
{
    //use data
}

The above works just fine.
However, because HandleData can be called hundreds or even thousands of times a second (depending on the exact hardware module) and the data string can also be quite long, it creates a noticeable pressure on the GC.

I would like to avoid the creation of all those strings and instead receive the data as char[] or even byte[] as I just need to extract a few fields.
I tried to substitute 'string' with StringBuilder or char[] but that didn't work.

Additional information:
- The native library passes the data as char * (null terminated string)
- The memory is allocated and released by the native code
- .NET version: 4.5

I would appreciate your help.
Thank you!


Solution

  • Have you tried changing callback signature like this?

    [UnmanagedFunctionPointer(CallingConvention.StdCall)]
    public delegate void Data(IntPtr data);
    
    
    private unsafe static void HandleData(IntPtr data)
        {
            byte* charPtr = (byte*)data;
    
            // work with bytes here (which are single-byte chars).
    
    
        }
    

    Here you need to be cautios and check for null character manually.