Skip Menu |

This queue is for tickets about the Win32-API CPAN distribution.

Report information
The Basics
Id: 78081
Status: resolved
Priority: 0/
Queue: Win32-API

People
Owner: Nobody in particular
Requestors: BULKDD [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.68
Fixed in: (no value)



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.
On Wed Jun 27 22:04:41 2012, BULKDD wrote: Show quoted text
> 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
On Thu Jun 28 04:14:26 2012, ACALPINI wrote: Show quoted text
> 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.
Subject: output.txt
version is 0.62 $VAR1 = [ "LCCxxL", [ 1, 193, 194, 2 ], [ bless( { "__typedef__" => "FOO", "dw1" => 1, "dw2" => 2, "strt1" => bless( { "__typedef__" => "FOO2", "c1" => 193, "c2" => 194, "typedef" => [ [ "c1", "C", "UCHAR" ], [ "c2", "C", "UCHAR" ] ] }, 'Win32::API::Struct' ), "typedef" => [ [ "dw1", "L", "DWORD" ], [ "strt1", ">", "FOO2" ], [ "dw2", "L", "DWORD" ] ] }, 'Win32::API::Struct' ), $VAR1->[2][0]{"strt1"}, $VAR1->[2][0]{"strt1"}, $VAR1->[2][0] ], 12 ]; $VAR1 = "\1\0\0\0\301\302\0\0\2\0\0\0"; $VAR1 = [ "LL", [ 1, 2 ], [ bless( { "__typedef__" => "FOOPTR", "dw1" => 1, "dw2" => 2, "strt1" => bless( { "__typedef__" => "LPFOO2", "c1" => 193, "c2" => 194, "typedef" => [] }, 'Win32::API::Struct' ), "typedef" => [ [ "dw1", "L", "DWORD" ], [ "strt1", ">", "LPFOO2" ], [ "dw2", "L", "DWORD" ] ] }, 'Win32::API::Struct' ), $VAR1->[2][0] ], 8 ]; $VAR1 = "\1\0\0\0\2\0\0\0";
Subject: struct.t
use strict; use warnings; use Win32::API::Struct; use Data::Dumper; print "version is ".$Win32::API::Struct::VERSION."\n"; Win32::API::Struct->typedef("FOO2", qw( UCHAR c1; UCHAR c2; )); #as FOO2, pack code is LCCxxL, sounds right #as LPFOO2, pack code is LL, which is wrong Win32::API::Struct->typedef("FOO", qw( DWORD dw1; FOO2 strt1; DWORD dw2; )); my $struct = Win32::API::Struct->new("FOO"); $struct->{dw1} = 1; $struct->{strt1}->{c1} = 0xc1; $struct->{strt1}->{c2} = 0xc2; $struct->{dw2} = 2; print Dumper([$struct->getPack()]); $struct->Pack(); print Dumper($struct->{buffer}); Win32::API::Struct->typedef("FOOPTR", qw( DWORD dw1; LPFOO2 strt1; DWORD dw2; )); $struct = Win32::API::Struct->new("FOOPTR"); $struct->{dw1} = 1; $struct->{strt1}->{c1} = 0xc1; $struct->{strt1}->{c2} = 0xc2; $struct->{dw2} = 2; print Dumper([$struct->getPack()]); $struct->Pack(); print Dumper($struct->{buffer});
On Thu Jun 28 12:43:36 2012, BULKDD wrote: Show quoted text
> 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. Show quoted text
_____________________________________ 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.
_____________________________________