Subject: | ::Struct inside ::Struct is always inline, never a pointer |
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.