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
[AlsoUsableFor] and [RAIIFree] #389
Comments
For now, I'm just assuming the type/function is in the same namespace as the type that includes the attribute but I'm guessing that may not always be the case. |
I can fix it fairly easily. And HeapDestroy, it would include the class, right? Windows.Win32.SystemServices.Apis.HeapDestroy |
No, the |
The attributes are only in the metadata, so IMO they should refer to other members by their metadata names. The |
What I mean is that the very existence of the The C++ and Rust parsers perform type lookup via a two-string key consisting of namespace and name. In the example presented here, that would be "Windows.Win32.SystemServices" and "HeapDestroy". The |
Ok, fair enough. |
I don't see any other way to represent methods in metadata without putting them on a type, or maybe you know how to do it. I would be happy to get rid of the Apis class if I can. I'm using a metadata writer to output to metadata, even though I start by walking a C# syntax tree generated by ClangSharp. I have flexibility to move away from C# when we need to (which I'm already doing a lot). |
I think you're right. Software is full of compromise and this just seemed like one of those concessions we had to make to get the job done given the constraints we were given, metadata formats and such. I also didn’t fully grasp that you had moved away from a purely C# driven approach to metadata generation, so I was still thinking that’s all we had to work with. I have to say that I’m thrilled with what you've come up with for win32 metadata. For years I’ve dreamed of having metadata for Win32 APIs and you’ve single-handedly made that a reality. The only reason I made that comment about methods and classes is that IL technically supports free functions. I happen to know that because I wrote about it many years ago, but its been so long I have no idea whether that would work for us in practice nor does it really matter. The Apis class is perfectly fine – it doesn’t bother me in the least. My only point really was that the Apis class is just the construct we use for grouping functions within namespaces. It’s not part of the fully-qualified name of the function, at least in the way that I think about it – every construct has a namespace and a name – and in that worldview there’s no room for the Apis class name. But I can see how that is somewhat subjective. 😊 I'm sorry if I gave the impression of being critical of the implementation. Far from it - I'm really quite thrilled. |
This is probably a silly idea, but you could get rid of namespace Windows.Win32.ActiveDirectory
{
public static class Apis
{
public const uint ACTRL_DS_CONTROL_ACCESS = 256u;
...
}
public struct AccessControlEntry { }
...
} You could do this: namespace Windows.Win32
{
public static class ActiveDirectory
{
public const uint ACTRL_DS_CONTROL_ACCESS = 256u;
...
public struct AccessControlEntry { }
...
}
} This would remove the need for the |
IMHO no, it doesn't, but it really depends on how you see it. The convention is to put "free" functions on the hidden module class. I don't know how well established this pattern is with tooling (maybe its even standardized somewhere), but at the end its just convention. Considering that the hidden module class is global you would lose the ability to classify methods by namespace/component if you pick up this convention. |
I finally tried implementing [RAIIFree("Windows.Win32.WindowsProgramming.CloseHandle")]
[NativeTypedef]
public struct HANDLE
{
public IntPtr Value;
} But perhaps |
Same for Same for HICON/HMENU/HCURSOR and possibly others. |
There are two When we have namespaces prepended to these attributes, should that prepended string include |
Or another option is add |
I didn't think this was possible since the C/C++ headers don't use namespaces to resolve conflicts like this...? |
I see there's a It looks like the audio one is documented here: https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee417724(v=vs.85) So it looks like it comes from "dsound.h". I'm not seeing where the tpm version of |
@marler8997 From what I've heard, conflicting method names do exist in Win32, but typically in different enough areas that you can avoid the ambiguity by including only one of the header files. |
How about using typerefs in these two attributes instead of fully-qualified strings? [RAIIFree(typeof(Windows.Win32.SystemServices.Apis), "HeapDestroy")]
[AlsoUsableFor(typeof(Windows.Win32.SystemServices.HeapHandle))] That would leverage the metadata for what ECMA-335 can efficiently represent, so the metadata would likely get slightly smaller. It also gives the projection code a convenient way to get each of the three string elements (namespace, class name, and method name) that they may need without allocating strings unnecessarily. |
According to ECMA-335 6th ed. II.23.3 Custom attributes, an argument for a parameter of type System.Type is encoded as a string anyway. How would that save anything? Or were you going to use a constructor with a different parameter type?. |
@AArnott that format would be fine with me. |
@KalleOlaviNiemitalo It's not that we avoid strings in the metadata, since yes every type reference is encoded as a string, like you say. |
@AArnott My recollection is that I didn't get a TypeReferenceHandle for attribute arguments that were type constants, but I had to parse the string myself. I filed an issue with S.R.Metadata to provide a decoder because it was tedious. (Perhaps I'm confused and it was only enum constants cast to object though.) |
Yes, internally it is encoded as a string in the attribute blob. The C# parser probably hides this detail. |
Generated C# looks correct but ILSpy only shows typeof(Type).
I attempted to update RAIIFree to use the proposed model at f0deee3. The generated C# looks as expected, but I'm not sure it's translating to the winmd properly. ILSpy just shows @AArnott could you take a look? Given the generated C# code looks correct, I'm not sure if this is an ECMA-335 issue, winmd issue, ILSpy issue, or something else. |
Note that storing the namespace as a type doesn't actually make things better. As I mentioned this is just encoded as a string anyway, but the real problem is that the function name is still stored as a string rather than a |
If the [RAIIFree("Windows.Win32.Graphics.OpenGL", 7821)] |
The methods of a class have to be consecutive, and the methods of a COM interface have to be in the vtable order; but would it be feasible to sort the methods of Is it possible that a metadata assembly of an extension SDK will need to use RAIIFreeAttribute on a type of its own (or a parameter or a return value, if supported) but reference a freeing method in the Windows SDK metadata? In that case, the MethodDef row ID would not be reliable, as the version might not match exactly. |
Yes, a simpler approach may be to guarantee that the functions in the [RAIIFree("Windows.Win32.Graphics.OpenGL.wglDeleteContext")] |
Don't think that'll be possible as metadata relies on .NET for the build up and emission of the winmd, and I don't think there are any ordering guarantees or knobs to tweak there. Will take a deeper look though! |
Assigning to you @riverar since it sounds like you've gotten pretty far with this already. |
At this point, all
Should we just move these Looking at the metadata now compared to 2 years ago when this was filed, I think it's fair to enforce that all |
That's fine with me. |
These attributes refer to other types without including their namespace, making it difficult to use in any meaningful way. It should ideally be something like this:
The text was updated successfully, but these errors were encountered: