10

Is there a convenient way handle C typedef which may have different value on various platform ?

For example

#if defined(_WIN32)
    #define foo_t int32_t
#elif defined(_WIN64)
    #define foo_t int64_t
#else
    #define foo_t long
#endif

void handle_foo(foo_t* in) {
    ...
}

Currently I am handle this in Perl 6 like this

sub handle_foo32(int32 is rw) is native(Str) { * }
sub handle_foo64(int64 is rw) is native(Str) { * }
sub handle_foo00(long  is rw) is native(Str) { * }

sub handle-foo(Int $in) {
    if $*DISTRO.is-win {
        given $*KERNEL.bits {
            when 32 {
                handle_foo32(my int32 $ = $in);
            }
            when 64 {
                handle_foo64(my int64 $ = $in);
            }
        }
    } else {
        handle_foo00(my long $ = $in);
    }
}
jjmerelo
  • 22,578
  • 8
  • 40
  • 86
araraloren
  • 185
  • 7
  • Is there a deeper logic behind the different typedefs and their conditions? What do you want to achieve? The C way is usually to use a header which defines the semantic you want and not so much care about the details. – Yunnosch May 21 '18 at 13:10
  • @Yunnosch: this is about trying to interface with native libraries *without* using a C-compiler. So there is on way to just use a header file to get the right sematics. – Elizabeth Mattijsen May 21 '18 at 13:13

2 Answers2

9

Perhaps the most direct translation is to use constant to introduce a new symbol, computed at compile time.

my constant foo_t = do if $*DISTRO.is-win {
    given $*KERNEL.bits {
        when 32 { int32 }
        when 64 { int64 }
    }
} else {
    long
}

A constant bound to a type object acts just like a type, and can be used in the signature.

sub handle_foo(foo_t is rw) is native { * }
Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105
Jonathan Worthington
  • 29,104
  • 2
  • 97
  • 136
4

I don't think so. But since $*DISTRO.is-win and $*KERNEL.bits are effectively constants, you can move the decision on which version to use to compile time:

sub handle_foo32(int32 is rw) is native(Str) { * }
sub handle_foo64(int64 is rw) is native(Str) { * }
sub handle_foo00(long  is rw) is native(Str) { * }

my constant &handler = $*DISTRO.is-win
  ?? $*KERNEL.bits == 32
    ?? &handle_foo32
    !! &handle_foo64
  !! &handle_foo00;

Except this won't of course help you with the differently sized parameters for each version. So I guess you would need another layer of indirection for that.

Perhaps as inspiration, here's how I handled similar issues: https://github.com/lizmat/P5getpwnam/blob/master/lib/P5getpwnam.pm6

Elizabeth Mattijsen
  • 25,654
  • 3
  • 75
  • 105