Skip to content

Explain type matrix #98

@ethindp

Description

@ethindp

From what I can tell, there isn't a description of how to map unions to .NET types. This is a problem for me since I have an API that uses unions and I'd like to bind it using this library. It would also be nice if there was something like a reference sheet that described both simple and complex types in C mapped to the associated simple and complex types in .NET. According to this SO question, the StructLayout attribute combined with the FieldOffset can simulate this with structs, but I don't know how well this would map across the FFI boundary. The library I'm binding has the following structs and associated union:

struct syz_AutomationPoint {
  int interpolation_type;
  double values[6];
  unsigned long long flags;
};

struct syz_AutomationAppendPropertyCommand {
  int property;
  struct syz_AutomationPoint point;
};

struct syz_AutomationClearPropertyCommand {
  int property;
};

struct syz_AutomationSendUserEventCommand {
  unsigned long long param;
};

union syz_AutomationCommandParams {
  struct syz_AutomationAppendPropertyCommand append_to_property;
  struct syz_AutomationClearPropertyCommand clear_property;
  struct syz_AutomationSendUserEventCommand send_user_event;
};

struct syz_AutomationCommand {
  syz_Handle target;
  double time;
  int type;
  unsigned int flags;
  union syz_AutomationCommandParams params;
};

SYZ_CAPI syz_ErrorCode syz_createAutomationBatch(syz_Handle *out, syz_Handle context, void *userdata,
                                                 syz_UserdataFreeCallback *userdata_free_callback);
SYZ_CAPI syz_ErrorCode syz_automationBatchAddCommands(syz_Handle batch, unsigned long long commands_len,
                                                      const struct syz_AutomationCommand *commands);
SYZ_CAPI syz_ErrorCode syz_automationBatchExecute(syz_Handle batch);

Therefore, one possible implementation of this translation might be:

using System.Runtime.InteropServices;

// ...
public struct AutomationPoint {
    public int InterpolationType;
    public double[6] Values;
    public ulong Flags;
}

public struct AutomationAppendPropertyCommand {
    public nint Property;
    public AutomationPoint Point;
}

public struct AutomationClearPropertyCommand {
    public int Property;
}

public struct AutomationSendUserEventCommand {
    public uint param;
}

[StructLayout(LayoutKind.Explicit, Pack=1)]
public struct AutomationCommandParams {
    [FieldOffset(0)]
    public AutomationAppendPropertyCommand AppendToProperty;
    [FieldOffset(56)]
    public AutomationClearPropertyCommand ClearProperty;
    // ...
}

The only major problem with this is that its majorly error-prone. I could use the sizeof operator but I'm not quite sure how I'd use that since FieldOffset requires a contiguous range. Is there a much better way of doing this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions