Wed Jun 27 22:04:41 2012: Request 78081 was acted upon. Transaction: Ticket created by BULKDD Queue: Win32-API Subject: ::Struct inside ::Struct is always inline, never a pointer Broken in: 0.68 Severity: Normal Owner: Nobody Requestors: bul...@cpan.org Status: new Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=78081 >
I am filing this as a RT bug, but I hope I get responses from libwin32 readers and not just API's 2 maintainers. It seems to me that currently, in 0.68, and 0.70, if you create a ::Struct, with another ::Struct, as a member, the child ::Struct is always inlined into the parent struct. A ::Struct can not have a ::Struct pointer as a member. There is no code path to create such a thing. Also there is no public api way of obtaining a pointer to the packed ::Struct string scalar. So I ask, how should the API to create a ::Struct * member of a ::Struct be? My currently I have 5 ideas currently ::Struct::typedef is =item C<typedef NAME, TYPE, MEMBER, TYPE, MEMBER, ...> idea 1: typedef(POINTERNAME, EXISTING_TYPE) or typedef(NAME, TYPE, MEMBER, TYPE, MEMBER, ...) #legacy proto with die "usage Win32::API::Struct::typedef( NAME, [NON_POINTER_STRUCT_NAME] | [TYPE, MEMBER, TYPE, MEMBER, ...])" if scalar(@_) % 2 == 0 && scalar(@_) != 2; an even @_ is broken usage currently, if @_ is even and @_ has 2 slices, instead of broken usage, have that be pointer typedef mode idea 2: ::Struct::typedef unchanged ::Struct::make_pointer($name, $existing_struct); # named after private is_pointer() or decl_pointer instead of make_pointer? someone might think make_pointer returns an IV to the packed struct. idea 3: ::Struct::typedef unchanged ::Struct::is_pointer($name [, $set_bool]) #name after private api in ::Type, proto diff tho permanently converts struct $name to a struct pointer, user should probably have $name begin with LP or P for user's sanity but not enforced, you must call typedef again and recreate the struct from the member elements all over again under a new name if you want the non-pointer version after calling is_pointer idea 4: ::Type::typedef has * detection in, so "Win32::API::Type->typedef('LPMY_STRUCT', 'MY_STRUCT *');" idea 5: expose as public api getting the pointer suitable for passing to a UINT_PTR or 'N' letter param, from a Win32::API::Struct object instance. Document it in POD how to get raw pointer from a Win32::API::Struct object instance. Dont mess with the type databases. This is easiest solution BTW quasi idea 6: change ::Type::typedef to have 3 parameters, 3rd param signals struct pointer creation mode I dont like it. not an idea: No extending the "LP" detection. Many late 2000s added to Platform SDK MS structs only come in P variants, not LP. Something like typedef struct pvalueW { // Provider supplied value/context. LPWSTR pv_valuename; // The value name pointer int pv_valuelen; LPVOID pv_value_context; DWORD pv_type; }PVALUEW, FAR *PPVALUEW; would be a problem. Some background comments. There is also no integration between ::Type's type database (%Pointer, %Known) and ::Struct's type database (%Known). Ideally one day ::Type and ::Struct will be merged much closer, so ::Type's Pack()/Unpack() processes ::Struct types rather than current the separate callbacks into Perl language in API.xs but I don't have time to rewrite so much code. There is also the separate issue of no pass by copy structs support. On x86 pass by copy structs are placed on the stack, it can be work arounded today by unpacking the packed struct into a bunch of Ns, then prototyping the func as Ns. On x64, AFAIK, >8 becomes pointer so the workaround isn't portable.