当用 Python ctypes 模块调用动态链接库,如何传入一个结构体指针

最近用 dv2xvid 这个东东很多,上两周几乎每天都用它跑一个晚上压缩2个小时的视频。于是又萌发了把它改进得更通用的念头。

目前 dv2xvid 有一个很严重的问题,就是只支持 xvid-1.1.0-beta2 的压缩。而事实上目前大家用的最多的是应该都是正式版本,比如 1.0.3 或者 1.1.0 之类。如果想能支持更多版本的 xvid codec,就必须能在压缩之前判断 xvid 的版本。

恶心的是安装的 xvid 的目标文件没有 Windows Dll 的版本属性,查了半天,调用 xvidcore.dll 里面的一个函数可以获得 xvidcore.dll 的版本号

#include "xvid.h"

{
  xvid_gbl_info_t info;
  HINSTANCE m_hdll;

  memset(&info, 0, sizeof(info));
  info.version = XVID_VERSION;
  m_hdll = LoadLibrary(XVID_DLL_NAME);
  if (m_hdll != NULL) {
    ((int (__cdecl *)(void *, int, void *, void*))
GetProcAddress(m_hdll, "xvid_global"))(0, XVID_GBL_INFO, &info, NULL);
    
   printf("xvidcore.dll version %d.%d.%d (\"%s\")",
                XVID_VERSION_MAJOR(info.actual_version),
                XVID_VERSION_MINOR(info.actual_version),
                XVID_VERSION_PATCH(info.actual_version),
                info.build);

    FreeLibrary(m_hdll);
  } else {
    printf("xvidcore.dll not found!");
  }
}

如果在 python 里面做到这个事情,可以通过 ctypes 模块来完成。但查遍 ctypes 有关的中文文档,都没有关于怎样在函数中传入结构体指针的说明,只能自己 google 之,后来发现应该这么来做:

from ctypes import *

### 定义结构体
class xvid_gbl_info_t(Structure):
    _fields_ = [("version", c_int),
                ("actual_version", c_int),
                ("build", c_char_p),
                ("cpu_flags", c_uint),
                ("num_threads", c_int)]

XVID_GBL_INFO = 1

dll = cdll.load("c:\\windows\\system32\\xvidcore.dll")
xvid_global = dll.xvid_global

### 构造 pinfo 结构体, 然后赋值
pinfo = xvid_gbl_info_t()
pinfo.version = ((((1)&0xff)<<16) | (((0)&0xff)<<8) | ((0)&0xff))

= c_voidp(0)
= c_voidp(0)
### 用 byref 传入指针
if xvid_global(x, c_int(XVID_GBL_INFO), byref(pinfo), y) == 0:
    major_version = (pinfo.actual_version>>16)&0xff
    minor_version = (pinfo.actual_version>>8)&0xff
    patch_version = (pinfo.actual_version>>0)&0xff
    print major_version, minor_version, patch_version
    print pinfo.build
    print pinfo.cpu_flags
    print pinfo.num_threads
else:
    print "ERROR"



转自:http://www.dup2.org/node/150

展开阅读全文

没有更多推荐了,返回首页