2014-10-17 100 views
2

我想从一个软件SDK中提供一个DLL文件并创建一个python包装,以便将其与我的其他代码库相集成。我在网上关注了很多指南,仍然没有运气。如何为一个DLL库创建一个Python包装

目前的Python代码我是:

from ctypes import * 
from ctypes.wintypes import HWND 
import os 

class OptistarDLL(object): 
    dll_path = 'OSDS142MRT.dll' 

    with open(dll_path) as thefile: 
     pass 

    _dll = WinDLL(dll_path) 

    init_library = _dll['OSDS142M_Initialize'] 
    init_library.restype = c_int 
    init_library.argtypes = (c_int, c_bool, HWND, c_bool, c_int) 


class OpticstarControl(object): 

    def __init__(self): 
     err = OptistarDLL.init_library(c_int(0), c_bool(False), HWND(0), c_bool(False), c_int(0)) 
     if err != 0: 
      raise Exception("Doom") 

我使用的SDK文档提供了以此为函数的头:

DLLDIR int OSDS142M_Initialize(int iModel, bool bOutVid, HWND hwOutVid, bool bStarView, int iRt); 

而且例如PDF给出:

OSDS142M_Initialize(1, false, 0, true, 0); 

初始化目前仅让我知道

ValueError: Procedure probably called with too many arguments (20 bytes in excess) 

我看了,但不被理解,关于WinDLL VS CDLL,当我改变CDLL DLL的加载失败。我也在所有的指南中看到,其中的标题有DLLEXPORT,我的DLLDIR,我不知道这是否是一个问题。

有没有人有任何想法?

回答

2

考虑到问题中的信息,最可能的解释是DLL使用cdecl而不是stdcall。您使用WinDLLstdcall DLL匹配。改用CDLL来切换到cdecl调用约定。

错误消息与此一致。调用约定之间的区别在于stdcall已被调用堆栈清理,而cdecl有调用者清理。这些参数在堆栈上占用20个字节,其中5个参数的大小均为4.并且ctypes将这些参数推入,并期望被调用者清理堆栈。它不这样做,因为它是一个cdecl函数。

您对该函数的调用是不必要的复杂。您可以编写:

err = OptistarDLL.init_library(0, False, 0, False, 0) 

请注意,您引用的示例调用会传递不同的参数。为了匹配的呼叫你可以这样写:

err = OptistarDLL.init_library(1, False, 0, True, 0) 

你当然应该删除这些代码:

with open(dll_path) as thefile: 
    pass 

那没有其他目的,而不是浪费时间。如果DLL不存在,您将很快遇到失败。

+0

嗨大卫,当试图通过'CDLL'调用时,我得到一个返回码13.然而,它看起来实例化没有像在WinDLL一样失败,在某种意义上该方法实际上是被调用的。因此,我认为这可能是一个图书馆问题,所以我会用Opticstar来解决这个问题。 – Samreay 2014-10-18 03:23:56

+0

是的。返回代码的13个声音,如你的interop现在是正确的。 – 2014-10-18 07:34:17