Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explain type matrix #98

Open
ethindp opened this issue Aug 27, 2022 · 3 comments
Open

Explain type matrix #98

ethindp opened this issue Aug 27, 2022 · 3 comments

Comments

@ethindp
Copy link

ethindp commented Aug 27, 2022

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?

@Nihlus
Copy link
Owner

Nihlus commented Aug 28, 2022

Using FieldOffset and an explicit struct layout is the way to go when dealing with unions, I'm afraid - this is one of those parts that gets hairy quick.

@ethindp
Copy link
Author

ethindp commented Aug 28, 2022

@Nihlus Is there an easier way of computing the offsets, then? I really don't want to do [FieldOffset(sizeof(a) + sizeof(b) + sizeof(c) +...)]. That just looks really ugly.

@Nihlus
Copy link
Owner

Nihlus commented Aug 31, 2022

That's the only way I'm aware of, unfortunately. Interop code is ugly by its nature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants