-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
[ComInterfaceGenerator] Marshalling structs containing strings/interfaces #88284
Comments
Tagging subscribers to this area: @dotnet/interop-contrib Issue DetailsIt currently does not appear to be possible to emit structs from COM interfaces using the new COM interface generator that contain string or interface fields. According to the UserTypeMarshallingV2 design document, the expectation appears to be that either a completely custom "native" declaration of the type is provided, or a
While the design document states that Assuming public struct StructWithString
{
//Note: not currently valid as MarshalUsingAttribute is disallowed on fields
[MarshalUsing(typeof(Utf16StringMarshaller))]
public string field;
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44")]
[GeneratedComInterface]
public partial interface Iface
{
void M1(out StructWithString value);
} Less clear is how a struct should be marshalled containing an interface type public struct StructWithIface
{
public Iface field;
}
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44")]
[GeneratedComInterface]
public partial interface Iface
{
void M2(out StructWithIface value);
} The above currently gives an error that Decorating string/interface fields in structs with
|
As I understand it, permitting You would instead need to have a marshaller for With that in mind, it seems to me that a better approach might be to have some kind of public partial struct StructWithString
{
[MarshalFieldUsing(typeof(Utf16StringMarshaller))]
public string field;
[GeneratedCustomMarshaller(typeof(StructWithString))]
public static partial class Marshaller
{
}
}
// ...
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44")]
[GeneratedComInterface]
public partial interface Iface
{
void M1([MarshalUsing(typeof(StructWithString.Marshaller))] out StructWithString value);
} |
Rather than have to declare an empty marshaller yourself, I would imagine what should happen is similar to what is described in the V1 StructMarshalling document
// User code
[GeneratedMarshalling]
public partial struct StructWithString
{
[MarshalFieldUsing(typeof(Utf16StringMarshaller))]
public string field;
} //Generated code
file struct NativeStructWithString
{
//whatever the native representation of the string field should be
}
public partial StructWithString
{
//Inside StructWithString so the marshaller can access private fields
[CustomMarshaller(typeof(StructWithString), ...]
public static class Marshaller
{
public static StructWithString ConvertToManaged(NativeStructWithString unmanaged);
public static NativeStructWithString ConvertToUnmanaged(StructWithString managed);
//any other required methods
}
} If a struct is decorated with some attribute indicating it has generated custom marshalling, I would imagine it should "just work" at a given parameter site, using the generated custom marshaller by default without having to explicitly specify the custom marshaller to use |
The currently supported struct marshalling logic is either define the struct as blittable or implement a custom marshaller with |
Due to time constraints, we never implemented a "custom struct marshalling" generator. That work is tracked by #81656. I'm going to close this issue as a duplicate of that one (and make that the central issue for generated struct marshalling). |
It currently does not appear to be possible to emit structs from COM interfaces using the new COM interface generator that contain string or interface fields.
According to the UserTypeMarshallingV2 design document, the expectation appears to be that either a completely custom "native" declaration of the type is provided, or a
MarshalUsingAttribute
should be applied to the relevant field requiring custom marshalling.While the design document states that
MarshalUsingAttribute
should apply to fields, parameters and return values, the current definition ofMarshalUsingAttribute
only allows its use on parameters and return values.Assuming
MarshalUsingAttribute
should also be permissible on fields, I would assume this would solve the problem of structs containing strings by allowing you to do the following which is currently prohibited:Less clear is how a struct should be marshalled containing an interface type
The above currently gives an error that
StructWithIface
is not supported by source-generated COM. Given thatIface
contains a source generated interface, I expect that this should "just work". Alternatively, ifMarshalUsingAttribute
is supposed to be permissible on fields, a custom marshaller for marshalling interfaces could be applied, in which case it would make sense for there to be a built in custom marshaller for marshalling ComWrappers based interfaces, rather than every user having to define a general purpose interface marshaller themselves.Decorating string/interface fields in structs with
MarshalAsAttribute
does not have any effect with regards to either string or interface marshallingThe text was updated successfully, but these errors were encountered: