windows 如何从Python打开Win32 FILE*

6za6bjd0  于 2023-01-31  发布在  Windows
关注(0)|答案(1)|浏览(212)

我试图使用Win32 msvcrt.dll打开标准输出并打印出一些任意字符串。请记住,我不 * 不 * 想使用printmsvcrtos库。
我尝试使用_fdopen_fputs,但总是得到OSError: exception: access violation reading 0x0000000036B5FAA8。我认为问题是在python中不能有FILE*,它通过ctypes转换为int,但我不知道如何转换该内存地址(int)转换成一个实际的指针传递给函数。有可能我错了,我做的其他事情是不好的。
代码:

c = __import__('ctypes.util')
c_lib = c.CDLL(c.util.find_library('msvcrt'))

fptr = c_lib._get_osfhandle(
  c.cast(
    1,
    c.POINTER(c.c_int),
  )
)

realf = c_lib._open_osfhandle(
  fptr,
  c.cast(
    8,
    c.POINTER(c.c_int),
  )
)

fd = c_lib._fdopen(realf,
  c.cast(
    b'w',
    c.POINTER(c.c_char),
  )
)

c_lib.fputs(
 c.cast(
    b'Hello msvcrt!',
    c.POINTER(c.c_char),
  ),
    fd
)

c_lib._flushall()
c_lib._close(realf)

c_lib._exit(
  c.cast(
    0,
    c.POINTER(c.c_int)
  )
)

下面是我正在尝试做的事情,但是使用的是msvcrtos

import msvcrt, os

fptr = msvcrt.get_osfhandle(1)
realf = msvcrt.open_osfhandle(fptr, os.O_APPEND)
fd = os.fdopen(realf, 'w')

fd.write('hello')
fd.flush()

os.close(realf)

我怎样才能做同样的事情,但在前面的代码格式?我试图通过CPython源代码查看os.fdopen在内部做什么,但不可能找到任何东西(嵌套太多,github对搜索的支持很差)。在fd打开之前,代码的工作原理是一样的。但是,os.fdopen返回一个IO.TextIOWrapper,而fd返回一个很大的数字(十六进制36B5FAA8,但由于内存分配的差异,每次运行都会略有变化)

f0ofjuux

f0ofjuux1#

我需要明确地将_fdopen的返回类型指定为ctypes.c_void_p(未指定类型的指针),这样可以成功地工作。

# Specify the return type
c_lib._fdopen.restype = c.c_voidp
fd = c_lib._fdopen(realf,
  c.cast(
    b'w',
    c.POINTER(c.c_char),
  )
)

看起来Python试图猜测返回类型(并假设它不是指针),它会猜错并给予错误的结果,这会导致_fdopen函数试图写入不正确的位置,从而导致越界写入。

相关问题