Closed corliss closed 7 years ago
This turned out to be easy - just declare both types as struct
and change the marshaling code to:
public GlyphInfo[] GlyphInfo()
{
int length;
IntPtr glyphInfoPtr = HB.hb_buffer_get_glyph_infos(reference, out length);
var glyphInfos = new GlyphInfo[length];
for (int i = 0; i < length; ++i)
{
glyphInfos[i] = Marshal.PtrToStructure<GlyphInfo>(glyphInfoPtr + 20 * i);
}
return glyphInfos;
}
public GlyphPosition[] GlyphPositions()
{
int length;
IntPtr glyphPositionPtr = HB.hb_buffer_get_glyph_positions(reference, out length);
var glyphPositions = new GlyphPosition[length];
for (int i = 0; i < length; ++i)
{
glyphPositions[i] = Marshal.PtrToStructure<GlyphPosition>(glyphPositionPtr + 20 * i);
}
return glyphPositions;
}
Note: It would be even better to directly marshal the result of HB.hb_buffer_get_glyph_infos()
and HB.hb_buffer_get_glyph_positions()
into c# arrays, thereby avoiding the loop. Haven't figured out how to do that, but seems like a common enough situation so it should be possible. But at least this fixes the issue of allocating lots of tiny classes.
Yes! Good catch! Arrays like this should be possible, my P/Invoke knowledge is a bit rusty but I'll see if I can make it work
Currently
GlyphInfo
andGlyphPosition
are classes. Allocating large numbers of these puts a lot of pressure on the GC. Therefore, these should be structs.