函数调用中的结果指针

Resultpointer in function call

我想通过 ctype 使用 dll 中的函数。我可以毫无错误地调用函数,甚至函数的错误代码都是 0,这意味着函数成功完成。但是当我尝试访问时,结果变量 ist 是空的。

我几年前就在免费的 pascal 中实现了查找,现在将把它转移到 python。该接口允许通过 cdel 约定访问,我现在在 python 3.7.4 中使用 ctypes

重新实现

最后一个可用的 Pascal 原型是:

PROCEDURE pGetCallInfo(DriveInfo: pointer; ACall: pointer; AInfo: pointer;
    var AErrorCode: SmallInt); pascal; external 'raccd32a.dll';

我在 python 中最好的版本如下:


from ctypes import *
callBookDLL = CDLL('raccd32a')
AInfo = create_string_buffer(400)
err = callBookDLL.cGetCallInfo("self.txt_CallBookPath.text()","DG1ATN",AInfo)

结果是:

错了 0 AInfo.value b''

AInfo 应包含最大值。 400 个字符的长字符串缓冲区,结果包含名称、地址等。

因为我有第二个图书馆,所以我必须以同样的方式访问我的错误,但我找不到它。我认为我的问题是使用指针和类型转换。

我已经检查了 teh ctypes howto,但我无法解决这个问题。

到目前为止非常感谢...

勾选[Python 3.Docs]: ctypes - A foreign function library for Python。它包含(几乎)您需要的所有信息。

存在一些问题:

  1. ctypes 不支持 pascal 调用约定,只支持 cdeclstdcall(仅适用于 32 位)。这意味着(阅读手册后)您不应该使用 p* 函数,而应该使用 c* (或 s*)

  2. 您没有为函数指定 argtypes(和 restype)。这导致 UB。一些效果:

  3. 是一个程序(returnsvoid的一个函数)。反正这是个小问题

下面是一些示例代码(当然是盲目的,因为我没有测试):

#!/usr/bin/env python3

import sys
import ctypes


dll = ctypes.CDLL("raccd32a.dll")

cGetCallInfo = dll.cGetCallInfo
cGetCallInfo.argtypes = [ctypes.c_char_p, ctypes.c_char_p, ctypes.c_char_p, ctypes.POINTER(ctypes.c_short)]
cGetCallInfo.restype = None

ADriveInfo = self.txt_CallBookPath.text().encode()
#ADriveInfo = b"C:\callbook2019\"  # Notice the double bkslashes
ACall = b"DG1ATN"
AInfo = ctypes.create_string_buffer(400)
result = ctypes.c_short(0)
cGetCallInfo(ADriveInfo, ACall, AInfo, ctypes.byref(result))

@EDIT0:

从一开始,我想让你说传递给函数的第 1st 个参数没有多大意义。然后,还有关于 2nd 的问题。根据手册([AMT-I]: TECHNICAL INFORMATION about RACCD32a.DLL重点是我的):

ADriveInfo, ACall and AInfo are pointers to zero-terminated strings. These strings has to exist at the moment of calling xGetCallInfo. The calling program is responsible for creating them. AInfo must be long enough to comfort xGetCallInfo (at least 400 characters). Note: "Length of AInfo" refers to the length of the string AInfo points at. ADriveInfo and ACall are treated in the same manner for short.

In ADriveInfo the procedure expects the path to the CD ROM drive. Use "G:\" if "G:" designates the CD ROM drive with the callbook CD ROM. Keep in mind that this information is a *must* and the calling program has to know it. Note: If the active directory on drive G: is not the root, ADriveInfo = "G:" will lead to an error 3. So always use "G:\". The calling program has to ensure that the length of ADriveInfo does not exceed 80 characters.

ACall contains the call you are looking for, all letters in lower case, no additional spaces etc. The calling program has to ensure that ACall is not longer than 15 characters. However, there is no call longer than 6 characters in the database.