Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[rt.cpan.org #78081] ::Struct inside ::Struct is always inline, never a pointer

3 views
Skip to first unread message

Daniel Dragan via RT

unread,
Jun 27, 2012, 10:04:42 PM6/27/12
to libw...@perl.org
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.

Aldo Calpini via RT

unread,
Jun 28, 2012, 4:14:27 AM6/28/12
to libw...@perl.org
Thu Jun 28 04:14:26 2012: Request 78081 was acted upon.
Transaction: Correspondence added by ACALPINI
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 >


On Wed Jun 27 22:04:41 2012, BULKDD wrote:
> 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?

as mentioned in the documentation, when you create a structure named
"FOO", a pointer type "LPFOO" is created automatically. you can use
"LPFOO" as the type of a member in another structure. so I think this is
a non-issue.

cheers,
Aldo

Daniel Dragan via RT

unread,
Jan 8, 2013, 11:49:50 PM1/8/13
to libw...@perl.org
Tue Jan 08 23:49:49 2013: Request 78081 was acted upon.
Transaction: Correspondence added 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: open
Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=78081 >


On Thu Jun 28 12:43:36 2012, BULKDD wrote:
> On Thu Jun 28 04:14:26 2012, ACALPINI wrote:
> > as mentioned in the documentation, when you create a structure named
> > "FOO", a pointer type "LPFOO" is created automatically. you can use
> > "LPFOO" as the type of a member in another structure. so I think this is
> > a non-issue.
> >
> > cheers,
> > Aldo
>
> Doesn't work currently. "LPFOO2" has an empty (or undef?) typedef hash
> slice rather than the slice being the normal array ref. The problems
> seem to be related to the fact that LPFOO2 isn't in
> %Win32::API::Struct::Known.

Fixed in ff9621b595.

_____________________________________
When C<TYPE> contains a Win32::API::Struct type declared with
L<Win32::API::Struct/typedef> with " *" postfixed to C<TYPE> parameter,
C<NAME> will be a alias for the pointer version of the struct type.
Creating an alias for a struct type is not supported, you have to call
L<Win32::API::Struct/typedef> again. Passing a struct type as C<TYPE>
without the " *" postfix is not supported.
_____________________________________
0 new messages