【问题标题】:Using C++ code in Python with ctypes在 Python 中通过 ctypes 使用 C++ 代码
【发布时间】:2017-08-30 21:51:51
【问题描述】:

我有以下 C++ 并且两个函数都返回表示成功的 int 0。

#include "stdafx.h"
#include <iostream>
#include "scapi.h"


int main() {

    int ret;

    ret = sc_LoginByLogon(L"hostname.domain.ltd", L"admin", L"pass");
    std::cout << "LoginByLogon: " << ret << std::endl;

    void* out_p;

    ret = sc_GetUserInfoByUserLogon(L"username", &out_p);
    std::cout << "GetUserInfoByUserLogon: " << ret << std::endl;
}

我现在正在尝试在 Python 中为这两个函数创建一个包装器,并提出了以下代码:

import sys
import ctypes
from ctypes import *

# Load DLL into memory.
class SUserInfoApiV4(Structure):
    INTRFDEF_SIZE_RESERVED = 32
    _fields_ = [
                 ('m_nStructLength', c_int),
                 ('m_nVersion', c_short),
                 ('m_nSubVersion', c_short),
                 ('m_achReserved', c_char * (INTRFDEF_SIZE_RESERVED - sizeof(c_long))),
                 ('m_nAccessRights', c_long),
                 ('m_nUserType', c_short),
                 ('m_nUserId', c_int),
                 ('m_nSubRights', c_long),
                 ('m_nNotUsed1', c_int),
                 ('m_wzFullName', c_wchar * 101),
                 ('m_wzDescription', c_wchar * 101),
                 ('m_wzEMail', c_wchar * 101),
                 ('m_wzUserLogon', c_wchar * 21),
                 ('m_wzPassword', c_wchar * 17),
                 ('m_szCardNo', c_char * 40),
                 ('m_szPINCode', c_char * 5),
                 ('m_szPUKCode', c_char * 9),
                 ('m_nLogonFails', c_short),
                 ('m_bUserLocked', c_short),
                 ('m_bUserDisabled', c_short),
                 ('m_bAvoidPin', c_short),
                 ('m_bPrintAll', c_short),
                 ('m_bCardOpen', c_short),
                 ('m_nBillingModel', c_short),
                 ('m_nAccountingModel', c_short),
                 ('m_nUserRights', c_int),
                 ('m_bAllowEncryption', c_short),
                 ('m_bAllowCheckPrinting', c_char),
                 ('m_bAllowPmail', c_char),
                 ('m_bDenyRetain', c_char),
                 ('m_lCreationDate', c_long),
                 ('m_lLastLogin', c_long),
                 ('m_nServerId', c_int),
                 ('m_nDomainId', c_int),
                 ('m_nTreeNodeId', c_int),
                 ('m_nNid', c_int),
                 ('m_wzCostCode', c_wchar * 51)
    ]

def main(argv):
    # import library
    lib = ctypes.cdll.LoadLibrary('scAPI.dll')

    # login
    login = lib.sc_LoginByLogon('hostname.domain.ltd', 'admin', 'pass')

    # sc_GetUserInfoByUserLogon
    SUserInfoApiV4p = POINTER(SUserInfoApiV4)
    sc_GetUserInfoByUserLogon = lib.sc_GetUserInfoByUserLogon
    sc_GetUserInfoByUserLogon.argtypes = [c_wchar_p, POINTER(SUserInfoApiV4p)]
    sc_GetUserInfoByUserLogon.restype = c_int

    # get user object
    out_p = SUserInfoApiV4p()
    user = sc_GetUserInfoByUserLogon('username', byref(out_p))

    # debug
    print 'LoginByLogon: ' + str(login)
    print 'GetUserInfoByUserLogon: ' + str(user)
    #print 'Full name:', out_p.contents.m_wzFullName

if __name__ == '__main__':
    main(sys.argv)

代码应该可以运行,但在 Python 中,只有 sc_LoginByLogon 返回 0,而 sc_GetUserInfoByUserLogon 失败 (1)。 The documentation 只声明“1 = 一般失败”,所以我被卡住了。

任何明显的想法都将受到高度赞赏。

【问题讨论】:

  • 你不应该将 POINTER(c_void_p)() 传递给方法吗?看来您传递的是不同的类型
  • 我尝试将 out_p 更改为 out_p = POINTER(c_void_p)(),但这给了我相同的结果。它仍然失败。
  • out_p = 指针(c_void_p()) ?
  • 这会引发“TypeError: must be a ctypes type”异常。我很确定定义是正确的......
  • 如果没有为sc_LoginByLogon 定义argtypes,Python 2 传递的字节字符串不会被隐式编码为Unicode 字符串。我希望第一个电话会失败。第二次调用看起来声明正确,但由于第一次调用的问题,它可能会失败。

标签: python c++ ctypes


【解决方案1】:

感谢 Mark Tolonen,它现在可以在调用前显式定义登录函数后工作。没想到我必须这样做,因为它已经返回了表示成功的 int 0。

唯一的问题是“m_wzFullName”等所有属性由于某种原因跳过了第一个字符。

编辑: 由于这个线程,我解决了最后一个错误: python ctypes pragma pack for byte aligned read

# sc_LoginByLogon
sc_LoginByLogon = lib.sc_LoginByLogon
sc_LoginByLogon.argtypes = [c_wchar_p, c_wchar_p, c_wchar_p]
sc_LoginByLogon.restype = c_int

【讨论】:

    猜你喜欢
    • 2019-10-21
    • 1970-01-01
    • 2017-01-02
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多