http://www.perlmonks.org?node_id=987866

bulk88 has asked for the wisdom of the Perl Monks concerning the following question:

I've done alot of work on a CPAN module. I need comments on the APIs that I added. Would how have implemented it differently? do you see an easier or more intuitive way to arrange the parameters? different function call names? Is the quads support not portable enough between native quad perls and 32 bit perls? Is the pod not clear enough?

Specifically I need comments on http://search.cpan.org/~bulkdd/Win32-API-0.70_02/API.pm#UseMI64, http://search.cpan.org/~bulkdd/Win32-API-0.70_02/API.pm#SafeReadWideCString, and http://search.cpan.org/~bulkdd/Win32-API-0.70_02/API.pm#q. There aren't public yet, so they can still be changed. Examples of the actual quads support are in the test file v70.t and 01_Struct.t in the tarball.

The changes are also at github as individual commits, https://github.com/bulk88/perl5-win32-api.

Replies are listed 'Best First'.
Re: RFC: Win32::API API
by roboticus (Chancellor) on Aug 16, 2012 at 20:33 UTC

    bulk88:

    UseMI64

    • I don't care for the name, but I can't think of anything better, either.
    • For the return value, I'd *always* return the 'before call' value, though. The reason being that if you want to query & change, you currently need two calls. But it's also for the principle of least surprise: I generally write (and see) "setter" type functions that return either the original object (so you can chain calls) or the prior value (so you can restore it after some operation).
    • I think I'd default the setting to 'on' if you're using a perl that doesn't support quads. (I contemplated suggesting using the 'Q' arg type there too, but it doesn't "feel" clean to me that way.)

    SafeReadWideCString

    I don't care for returning an empty string to signify the conversion error. I think I'd return undef or die on all errors so the user can catch it in an eval block. The empty string is too close to being legitimate, as the user might've passed an empty string *in*. If you want to split your errors into groups, I'd suggest returning undef for one group, and die for the other.


    Having said all that, keep in mind that these are my opinions, and they're worth exactly what you paid for 'em. ;^)

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      I'd go with either MathInt64 or UseMathInt64.

      I think I'd default the setting to 'on' if you're using a perl that doesn't support quads.

      Making it the default would require trying to load Math::Int64, and I can understand being reluctant to do that. Also, using it or not gives quite incompatible results so I don't think it should be too automatic. I'd leave it 'off' by default but I'd also make turning it 'on' fatal if Math::Int64 hasn't already been loaded.

      I agree with not returning an empty string for the failure case. I also don't like the name SafeReadWideCString(). Having a safe way to do it is certainly a big part of the motivation for providing this, but I don't find that worthy of inclusion in the name. Adding "C" as short for "Character" is as likely to be confusing as anything. 'Read' sounds more like an I/O operation than a memory operation.

      CopyWideToUtf8() works better for me for what you described. But I would personally appreciate having the ability to copy out the WCHAR string separate from the "convert to utf-8". If I'm going to make a bunch of WCHAR API calls, I may not want to convert the WCHAR to utf-8 just to have to convert it back again in order to pass it along to the next API. So maybe CopyWideString() also or CopyWideString() with an option to specify conversion or not.

      PWCHARtoPV()? Just kidding.

      I also like just being able to have 64-bit integers converted to/from NVs (double). For a huge range of values, there is no data loss. For some values, you lose some less-significant bits (which can be inappropriate for some uses but often is not a problem). I can certainly see not making this the default, of course.

      - tye        

        tye:

        For the default thing, I was thinking along the lines of leaving the setting to "on", but only load Math::Int64 on demand. In other words, I was hoping to *not* load it until someone actually defined an API using 'q'. But that would likely overcomplicate things.

        An alternative suggestion: If Math::Int64 is loaded and you're on a perl without quad support, *then* set the default to yes. Does that sound a bit more reasonable?

        Update: Ever since my eye trouble, I notice myself missing things. On re-reading, I notice that you already suggested my alternative proposal. (Note: Don't get a retinal tear. They suck. Six months later, and my left eye *still* looks like I'm looking through a snow-globe.)

        ...roboticus

        When your only tool is a hammer, all problems look like your thumb.

        Adding "C" as short for "Character" is as likely to be confusing as anything.

        I added the C since its only for Wide C strings, not Wide length tracked strings, for length tracked wide strings just use ReadMemory/memcpy to a scalar.

        I also like just being able to have 64-bit integers converted to/from NVs (double). For a huge range of values, there is no data loss. For some values, you lose some less-significant bits (which can be inappropriate for some uses but often is not a problem). I can certainly see not making this the default, of course.

        Risk of unintentional data/high bit loss is nearly guaranteed for someone who doesn't know C/perlguts and 2^53 limit.

        PWCHARtoPV()? Just kidding.

        I've been thinking about BADLPCWSTRTOMBCSPV jkjk.