Repository navigation
[API Proposal]: Add StringMarshalling property to GeneratedComInterfaceAttribute #84662
Copy link
Copy link
Closed
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Runtime.InteropServices
Milestone
Description
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
- Generate string marshalling based on the
StringMarshallingfield on theGeneratedComInterfaceAttributeAdd basic support for StringMarshalling in GeneratedComInterface #86404 - Ensure MarshalAs and MarshalUsing on the parameter/return overrides the interface-wide StringMarshalling StringMarshalling behavior override tests #86963
- Warn if inherited interfaces don't have the same
StringMarshallingandStringMarshallingCustomTypeas the base interface. [ComInterfaceGenerator] Warn if StringMarshalling doesn't match base and warn if base interface cannot be generated #86467 -
Warn if theWarn if StringMarshallingCustomType is less visible than 'internal' [ComInterfaceGenerator] Warn on visibility of interface and StringMarshallingCustomType #87065StringMarshallingCustomTypeis less visible than the interface.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
api-approvedAPI was approved in API review, it can be implementedAPI was approved in API review, it can be implementedarea-System.Runtime.InteropServices
Activity
jkoritzinsky commentedon Apr 11, 2023
jkoritzinsky commentedon Apr 11, 2023
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.
jtschuster commentedon Apr 12, 2023
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.
AaronRobinsonMSFT commentedon Apr 12, 2023
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.
bartonjs commentedon Apr 27, 2023
Video
Looks good as proposed
AaronRobinsonMSFT commentedon Apr 27, 2023
AaronRobinsonMSFT commentedon Apr 27, 2023
[ComInterfaceGenerator] Warn on visibility of interface and StringMar…