69507
こんにちは。

[ruby-ffi](https://github.com/ffi/ffi) で
[C言語で作成されたライブラリ](https://github.com/samtools/htslib) のバインディングを作成中です。  
ところが、一部の関数は実際には関数ではなく、関数形式マクロになっています。

例えば下記のような感じです。

```

    #define bam_is_rev(b) (((b)->core.flag&BAM_FREVERSE) != 0)
    #define bam_is_mrev(b) (((b)->core.flag&BAM_FMREVERSE) != 0)
    #define bam_get_qname(b) ((char*)(b)->data)
    #define bam_get_cigar(b) ((uint32_t*)((b)->data + (b)->core.l_qname))
    #define bam_get_seq(b)   ((b)->data + ((b)->core.n_cigar<<2) + (b)->core.l_qname)
    #define bam_get_qual(b)  ((b)->data + ((b)->core.n_cigar<<2) + (b)->core.l_qname + (((b)->core.l_qseq + 1)>>1))
    #define bam_get_aux(b)   ((b)->data + ((b)->core.n_cigar<<2) + (b)->core.l_qname + (((b)->core.l_qseq + 1)>>1) + (b)->core.l_qseq)
    #define bam_get_l_aux(b) ((b)->l_data - ((b)->core.n_cigar<<2) - (b)->core.l_qname - (b)->core.l_qseq - (((b)->core.l_qseq + 1)>>1))
    #define bam_seqi(s, i) ((s)[(i)>>1] >> ((~(i)&1)<<2) & 0xf)
    #define bam_set_seqi(s,i,b) ((s)[(i)>>1] = ((s)[(i)>>1] & (0xf0 >> ((~(i)&1)<<2))) | ((b)<<((~(i)&1)<<2)))
    
```

<https://github.com/samtools/htslib/blob/a79009b38ce83e39bcbc8f54c00cf203621aa5bb/htslib/sam.h#L251-L321>

型を決め打ちしてしまって大丈夫かな？という問題もあります。

しかし、それ以前にマクロは単にソースコードを置換するものだということなので ruby-ffi の`attach_function` または fiddle の
`extern` を使ってもこれら関数を追加できないのではないかと思います。（違っていたらごめんなさい）

こういった関数形式マクロを追加したい場合は、どのような方法が考えられますでしょうか？  
教えていただけると助かります。
CC BY-SA 4.0
2020-08-12T00:24:30.243
69468
2020-08-13T03:05:03.463
32772
question
ruby c
RubyのFFIまたはFiddleで関数形式マクロのバインディングを作る方法を教えてください
ruby-
ffiが呼び出すのはライブラリのソースコードではなく、コンパイルされたバイナリ（`.so`など）です。バイナリには関数名（シンボル）が含まれているので、ruby-
ffiはそれを使うことになります。ところが、マクロはコンパイル時に展開されバイナリには含まれませんので、ruby-
ffiはマクロの定義や、そもそもマクロが使われたかどうかすらわかりません。したがって、仰る通り`attach_function`を使ってマクロを呼び出すことはできません。

このようなマクロに相当する処理を実現するには、以下のような方法が考えられます。

  * Rubyでマクロを再現する。質問の例であれば、プロパティにアクセスする手段があればそれほど難しくないと思います。
  * C言語でマクロをラッパー関数として実装しなおして（引数・返り値の型を別途定めることになります）、ruby-ffiからはそのラッパーを呼び出す。構造体のメンバーにアクセスする関数が提供されていない場合でも、こちらの方法が使えます。

参考：[FFI: Foreign Function Interfaces for Fun &
Industry](https://spin.atomicobject.com/2013/02/15/ffi-foreign-function-
interfaces/)
CC BY-SA 4.0
2020-08-13T03:05:03.463
69507
2020-08-13T03:05:03.463
7500
69468
answer