【问题标题】:Handle C typedef on different platform using NativeCall使用 NativeCall 在不同平台上处理 C typedef
【发布时间】:2018-05-21 12:56:41
【问题描述】:

有没有一种方便的方法来处理在不同平台上可能具有不同价值的 C typedef?

例如

#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) {
    ...
}

目前我正在像这样在 Perl 6 中处理这个

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);
    }
}

【问题讨论】:

  • 不同类型定义及其条件背后是否有更深层次的逻辑?你想达到什么目标? C方式通常是使用一个定义你想要的语义的标题,而不是太关心细节。
  • @Yunnosch:这是关于尝试使用 C 编译器与本机库交互。所以有办法只使用一个头文件来获得正确的语义。

标签: c raku nativecall


【解决方案1】:

也许最直接的翻译是使用constant 引入一个新符号,在编译时计算。

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

绑定到类型对象的常量就像类型一样,可以在签名中使用。

sub handle_foo(foo_t is rw) is native { * }

【讨论】:

    【解决方案2】:

    我不这么认为。但由于$*DISTRO.is-win$*KERNEL.bits 是有效的常量,您可以将决定使用哪个版本来编译时间:

    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;
    

    除了这当然不会帮助您为每个版本设置不同大小的参数。所以我猜你需要另一层间接。

    也许作为灵感,我是这样处理类似问题的:https://github.com/lizmat/P5getpwnam/blob/master/lib/P5getpwnam.pm6

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-24
      • 2011-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      相关资源
      最近更新 更多