【问题标题】:help to convert python ctypes struct to 64bit帮助将 python ctypes struct 转换为 64bit
【发布时间】:2011-05-15 14:29:03
【问题描述】:

我发现此脚本附加到a thread in the fontforge-users mailing list正是我想要的。但是,它似乎只适用于 32 位系统,我真的很想在我的 64 位系统上使用它。

我做了一些阅读,但我不知道应该如何修改这个脚本(大概是 stuct?)以使其在 64 位架构下工作。有人可以帮忙吗?

干杯!

#!/usr/bin/python
# vim:ts=8:sw=4:expandtab:encoding=utf-8
# Export named font from PDF file using fontforge and ctypes

import sys
from ctypes import *

STRING = c_char_p
real = c_longdouble

# We need the `map` attribute of SplineFont, so declear an incomplete struct.
# see: http://sourceforge.net/projects/wqy/files/misc/
# file: fontforge-bindctypes-0.1.tar.bz2
class splinefont(Structure):
    pass
SplineFont = splinefont
splinefont._fields_ = [
    ('fontname', STRING),
    ('fullname', STRING),
    ('familyname', STRING),
    ('weight', STRING),
    ('copyright', STRING),
    ('filename', STRING),
    ('defbasefilename', STRING),
    ('version', STRING),
    ('italicangle', real),
    ('upos', real),
    ('uwidth', real),
    ('ascent', c_int),
    ('descent', c_int),
    ('uniqueid', c_int),
    ('glyphcnt', c_int),
    ('glyphmax', c_int),
    ('glyphs', POINTER(c_void_p)),
    ('changed', c_uint, 1),
    ('changed_since_autosave', c_uint, 1),
    ('changed_since_xuidchanged', c_uint, 1),
    ('display_antialias', c_uint, 1),
    ('display_bbsized', c_uint, 1),
    ('dotlesswarn', c_uint, 1),
    ('onlybitmaps', c_uint, 1),
    ('serifcheck', c_uint, 1),
    ('issans', c_uint, 1),
    ('isserif', c_uint, 1),
    ('hasvmetrics', c_uint, 1),
    ('loading_cid_map', c_uint, 1),
    ('dupnamewarn', c_uint, 1),
    ('encodingchanged', c_uint, 1),
    ('multilayer', c_uint, 1),
    ('strokedfont', c_uint, 1),
    ('new', c_uint, 1),
    ('compacted', c_uint, 1),
    ('backedup', c_uint, 2),
    ('use_typo_metrics', c_uint, 1),
    ('weight_width_slope_only', c_uint, 1),
    ('save_to_dir', c_uint, 1),
    ('head_optimized_for_cleartype', c_uint, 1),
    ('ticked', c_uint, 1),
    ('internal_temp', c_uint, 1),
    ('complained_about_spiros', c_uint, 1),
    ('use_xuid', c_uint, 1),
    ('use_uniqueid', c_uint, 1),
    ('fv', c_void_p),
    ('metrics', c_void_p),
    ('uni_interp', c_int),
    ('for_new_glyphs', c_void_p),
    ('map', c_void_p),
    # ...
]

def main():
    if len(sys.argv) != 3:
        print "Usage: %s doc.pdf fontname" % sys.argv[0]
        sys.exit(2)
    pdfname = sys.argv[1]
    fontname = sys.argv[2]
    fontfile = fontname + '.ttf'

    # ctypes functions
    libc = CDLL("libc.so.6")
    libc.fopen.restype = c_void_p
    libc.fopen.argtype = [c_char_p, c_char_p]

    lib_ff = CDLL('libfontforge.so.1')

    # SplineFont *_SFReadPdfFont(FILE *pdf,char *filename,
    #     char *select_this_font, enum openflags openflags)
    lib_ff._SFReadPdfFont.argtypes = [c_void_p, c_char_p, c_char_p, c_int]
    lib_ff._SFReadPdfFont.restype = POINTER(SplineFont)

    # int GenerateScript(SplineFont *sf, char *filename, char *bitmaptype,
    #     int fmflags, int res, char *subfontdefinition, struct sflist *sfs,
    #     EncMap *map, NameList *rename_to,int layer)
    lib_ff.GenerateScript.argytpes = [POINTER(SplineFont), c_char_p, c_char_p,
            c_int, c_int, c_char_p, c_void_p, c_void_p, c_void_p, c_int]
    lib_ff.GenerateScript.restype = c_int

    # need to somehow initialize libfontforge or it will segfault somewhere.
    lib_ff.doinitFontForgeMain()
    fobj = libc.fopen(pdfname, "rb")
    if not fobj:
        print "%s not found" % pdfname
        sys.exit(1)

    font = lib_ff._SFReadPdfFont(fobj, pdfname, fontname, 0)
    ret = 0
    if bool(font):
        ret = lib_ff.GenerateScript(font, fontfile, None, -1, -1, None, None,
                font.contents.map, None, 1)
    if ret:
        print 'Font export to "%s".' % fontfile
    else:
        print "** Error ** Failed to export font!!"

if __name__ == '__main__':
    main()

【问题讨论】:

  • 为什么有人用 Python 编写代码?这是我在 C 语言中为数不多的几件事之一。
  • @Sven Marnach - 我明白你的意思。从我自己的角度来看,我正在寻找一种从更复杂的 python 脚本中调用它的方法,所以这种方法,如果我能让它工作的话,对我很有吸引力。如果我能够用 C 重写它,我会对此持开放态度,但我想我仍然必须处理相同的架构问题?
  • 我看不出出现 64 位问题的原因,无论是在上面的 Python 代码中还是在 C 中重新编码的情况下。但是这个脚本的 C 版本会很短。您可以从 Python 中将其作为子进程或通过 ctypes 调用。
  • 你可以只运行 32 位版本的 Python
  • @David Heffernan:是的,这就是我目前正在做的事情,但这很尴尬而且完全不满意...... :)

标签: python struct 32bit-64bit ctypes


【解决方案1】:

问题是 /usr/include/fontforge/config.h 中是否定义了 FONTFORGE_CONFIG_USE_LONGDOUBLE。如果已定义,则代码的定义是正确的。在我的 amd64 linux 安装中,既没有定义 FONTFORGE_CONFIG_USE_LONGDOUBLE 也没有定义 FONTFORGE_CONFIG_USE_DOUBLE,所以我需要更改

real = c_float

有了这个改变,它就可以正常工作了。

【讨论】:

  • 非常感谢您的回答,但我无法复制您的结果!在我的安装(64 位 Ubuntu 10.10)中,/usr/include/fontforge/config.h 中也没有定义 FONTFORGE_CONFIG_USE_LONGDOUBLEFONTFORGE_CONFIG_USE_DOUBLE,但是将 real 的定义更改为 c_float 仍然会导致段错误。会不会是别的东西(也是)?
  • 为了进一步分析,您必须提供特定的 PDF 文件和特定的调用。我想不出任何其他可能导致问题的原因。
  • 感谢您的回复。如果您愿意看,我已经在此处发布了我的测试 pdf (simonwiles.net/test_fore.pdf) - 这只是我手头的第一个多语言测试工具。它只包含两种字体(PMingLiu 和 Gentium),脚本能够在 32 位系统上通过调用 python ff_font_extract.py test_fore.pdf BAAAAA+Gentiumpython ff_font_extract.py test_fore.pdf CAAAAA+PMingLiU 提取它们。请问您使用的是哪个 64 位 Linux 发行版? (ps. - 非常感谢您的帮助!)
  • 两种字体都可以随着更改导出。我正在使用 Debian 测试,libfontforge 0.0.20100501-2。我同意那些说用 C 写的更好的海报。
  • 感谢 Martin,我可以通过 Debian 测试和这个版本的 libfontforge 库来确认这一点。我会尝试找出差异,但你已经解决了。谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 2018-08-05
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多