Skip to content

[API Proposal]: Add StringMarshalling property to GeneratedComInterfaceAttribute #84662

Closed

Description

@jtschuster

Background and motivation

GeneratedComInterface does not support string marshalling with a StringMarshalling enum. To match the functionality of LibraryImport, GeneratedComInterface should also allow specifying a StringMarshalling value and an accompanying StringMarshallingCustomType. This would apply for all methods in the interface, as well as methods on interfaces that inherit from it if the inheriting interfaces do not specify their own StringMarshalling.

API Proposal

namespace System.Runtime.InteropServices.Marshalling;

[AttributeUsage(AttributeTargets.Interface)]
public class GeneratedComInterfaceAttribute : Attribute
{
    public StringMarshalling StringMarshalling { get; set; }
    public Type? StringMarshallingCustomType { get; set; }
}

API Usage

Example from crossgen2:

    [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)]
    [Guid("B029E51B-4C55-4fe2-B993-9F7BC1F10DB4")]
    internal partial interface ISymNGenWriter2 : ISymNGenWriter
    {
        void OpenModW(
                      string wszModule,
                      string wszObjFile,
                      out UIntPtr ppmod);

        void CloseMod(UIntPtr pmod);

        void ModAddSymbols(UIntPtr pmod, [MarshalAs(UnmanagedType.LPArray)] byte[] pbSym, int cb);

        void ModAddSecContribEx(
            UIntPtr pmod,
            ushort isect,
            int off,
            int cb,
            uint dwCharacteristics,
            uint dwDataCrc,
            uint dwRelocCrc);

        void QueryPDBNameExW(
            [MarshalUsing(CountElementName = nameof(cchMax))]
            char[] pdb,
            IntPtr cchMax);
    }

Alternative Designs

We could do a per-method string marshalling attribute, or continue using per-parameter MarshalAs / MarshaUsing attributes.

Risks

The ComInterfaceGenerator is new, so there aren't risks of regressions or breaking changes. No other risks come to mind.

Steps

Activity

  1. ghost added
    untriagedNew issue has not been triaged by the area owner
    on Apr 11, 2023
  2. removed
    untriagedNew issue has not been triaged by the area owner
    on Apr 11, 2023
  3. jkoritzinsky commented on Apr 11, 2023

    @jkoritzinsky
  4. jkoritzinsky commented on Apr 11, 2023

    @jkoritzinsky
    Member

    Also, I'm unsure if we want to propagate the setting across inheritance boundaries. While it's likely correct, it goes more towards the "spooky-action-at-a-distance" model that we've been trying to actively avoid with source-generated interop. Also, in the past we've discussed introducing an assembly-level attribute to specify the string marshalling rules, which would then conflict with the inheritance-based model if the base type was in a different assembly.

    I'd be interested to hear from the rest of the team as well as I might be in the minority here.

  5. jtschuster commented on Apr 12, 2023

    @jtschuster
    MemberAuthor

    Those are good points, and I think also it could be confusing if we generate shadowing methods for the base interfaces. Maybe it would be best to force StringMarshalling to be the same as the base interface? And if anyone needs different string marshalling than the base, they can use MarshalUsing/MarshalAs.

  6. AaronRobinsonMSFT commented on Apr 12, 2023

    @AaronRobinsonMSFT
    Member

    While it's likely correct, it goes more towards the "spooky-action-at-a-distance" model that we've been trying to actively avoid with source-generated interop

    Maybe it would be best to force StringMarshalling to be the same as the base interface?

    Agreed, and we can easily detect that in the analyzer and force propagation of the setting throughout the heirarchy. The gist is specify it once, it must be specified, and match, for everything below. Anything above should be "okay" because we require it if strings are involved so we should be set. It is sane and matches our expectations for being explicit about string encoding.

  7. added this to the 8.0.0 milestone on Apr 12, 2023
  8. added
    api-ready-for-reviewAPI is ready for review, it is NOT ready for implementation
    and removed
    api-suggestionEarly API idea and discussion, it is NOT ready for implementation
    on Apr 12, 2023
  9. bartonjs commented on Apr 27, 2023

    @bartonjs
    Member

    Video

    Looks good as proposed

    namespace System.Runtime.InteropServices.Marshalling;
    
    [AttributeUsage(AttributeTargets.Interface)]
    public partial class GeneratedComInterfaceAttribute : Attribute
    {
        public StringMarshalling StringMarshalling { get; set; }
        public Type? StringMarshallingCustomType { get; set; }
    }
  10. added
    api-approvedAPI was approved in API review, it can be implemented
    and removed
    api-ready-for-reviewAPI is ready for review, it is NOT ready for implementation
    on Apr 27, 2023
  11. AaronRobinsonMSFT commented on Apr 27, 2023

    @AaronRobinsonMSFT
    Member
  12. AaronRobinsonMSFT commented on Apr 27, 2023

    @AaronRobinsonMSFT
    Member
  13. added
    in-prThere is an active PR which will close this issue when it is merged
    on Jun 13, 2023
  14. removed
    in-prThere is an active PR which will close this issue when it is merged
    on Jun 14, 2023
  15. ghost locked as resolved and limited conversation to collaborators on Jul 14, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions