【お知らせ】プログラミング記事の投稿はQiitaに移行しました。

文字列配列を作る (3)

前回、Pythonで文字列配列をJITで表示しました。

マーシャリング(ポインタの変換など)はctypesに任せていたので、そこを手動でやってみます。前回と共通の部分(JIT)は、前回のコードを呼び出して処理しています。

mkstr2.py
from mkstr1 import *

def makebuf(args):
    ptrlen = len(args) * 4
    strlen = reduce(lambda x, y: x + len(y) + 1, args, 0)
    buf = (c_ubyte * (ptrlen + strlen))()
    iptr = 0
    istr = ptrlen
    for arg in args:
        buf[iptr:iptr+4] = conv32(addressof(buf) + istr)
        arglen = len(arg)
        buf[istr:istr+arglen] = map(lambda ch: ord(ch), arg)
        iptr += 4
        istr += arglen + 1
    return buf

strs = ["foo", "bar", "baz"]
buf = makebuf(strs)

print "addressof(buf) = " + hex(addressof(buf))
print map(lambda x: hex(x), buf)

f.argtypes = [c_void_p, c_void_p, c_int, c_void_p]
f(printf, putchar, len(strs), buf)

VirtualFree(p, 0, MEM_RELEASE)
実行結果
addressof(buf) = 0xb3e480
['0x8c', '0xe4', '0xb3', '0x0', '0x90', '0xe4', '0xb3', '0x0',
 '0x94', '0xe4', '0xb3', '0x0', '0x66', '0x6f', '0x6f', '0x0',
 '0x62', '0x61', '0x72', '0x0', '0x62', '0x61', '0x7a', '0x0']
foo bar baz

バッファを作ってそこに自前でポインタと文字列のデータを入れています。