使用Python调用C库

huangapple go评论65阅读模式
英文:

Using a C library with Python

问题

我正在编写一个在Linux下与以前格式编写的文件进行交互的Python程序('squishDB'格式,其中存储了来自旧的Fidonet网络的消息,时间跨度从1980年到2000年)。

为了与这些文件进行交互,我迄今为止已经使用了C和C++中的程序,它们使用libsmapi.so库,对于这些语言,该库工作得非常好。

现在,作为一个完全用Python编写的更大项目的一部分,我发现自己被迫使用相同的库来帮助我使用cstruct和ctypes,这是我以前从未使用过的。

我尝试编写这个简单的程序,它打开库并获取一个指针,然后可以调用各个函数。

import ctypes
import cstruct


class minf(cstruct.MemCStruct):
    __def__ = """
        struct _minf
        {
            short req_version;
            short def_zone;
            short haveshare;  /* filled in by msgapi routines - no need to set this */

            /* Version 2 Information */
            short smapi_version;
            short smapi_subversion;
        };
    """


def main():
    smapi = ctypes.CDLL('libsmapi.so')
    m = minf()

    m.def_zone = 2
    m.req_version = 0

    if smapi.MsgOpenApi(m):
        print("Error opening library")
        exit(1)


if __name__ == '__main__':
    main()

问题是,尽管我使用cstruct从C文件中逐字复制定义了minf()结构,但在将其传递给库调用时出现了这个奇怪的错误。

Traceback (most recent call last):
  File "/home/neo/progetti/PycharmProjects/smapitest/main.py", line 33, in <module>
    main()
  File "/home/neo/progetti/PycharmProjects/smapitest/main.py", line 27, in main
    if smapi.MsgOpenApi(m):
       ^^^^^^^^^^^^^^^^^^^
ctypes.ArgumentError: argument 1: KeyError: '_as_parameter_'

Process finished with exit code 1

有人能帮我吗?
谢谢。

祝好。

英文:

I'm writing a Python program under linux to interact with files written in an old format (the 'squishDB' format, where messages from the old Fidonet network were stored in the years from 1980 to 2000).

To interact with these files, I have so far used programs in C and in C++ they use the libsmapi.so library and with these languages the library works very well.

Now, as part of a larger project all written in Python, I find myself forced to use the same library helping me with cstruct and ctypes, which I had never used before.

I tried to write this simple program, which opens the library and gets a pointer, to then be able to call the individual functions.

import ctypes
import cstruct


class minf(cstruct.MemCStruct):
    __def__ = &quot;&quot;&quot;
        struct _minf
        {
            short req_version;
            short def_zone;
            short haveshare;  /* filled in by msgapi routines - no need to set this */
        
            /* Version 2 Information */
            short smapi_version;
            short smapi_subversion;
        };
    &quot;&quot;&quot;


def main():
    smapi = ctypes.CDLL(&#39;libsmapi.so&#39;)
    m = minf()

    m.def_zone = 2
    m.req_version = 0

    if smapi.MsgOpenApi(m):
        print(&quot;Error opening library&quot;)
        exit(1)


if __name__ == &#39;__main__&#39;:
    main()

The problem is that, despite having defined the minf() structure with cstruct by copying it verbatim from the C file, this strange error appears when I pass it to the library call.

Traceback (most recent call last):
  File &quot;/home/neo/progetti/PycharmProjects/smapitest/main.py&quot;, line 33, in &lt;module&gt;
    main()
  File &quot;/home/neo/progetti/PycharmProjects/smapitest/main.py&quot;, line 27, in main
    if smapi.MsgOpenApi(m):
       ^^^^^^^^^^^^^^^^^^^
ctypes.ArgumentError: argument 1: KeyError: &#39;_as_parameter_&#39;

Process finished with exit code 1

Anyone can help me?
Thanks.

Regards

答案1

得分: 1

cstructctypes 不兼容。请改用 ctypes.Structure 代替:

import ctypes as ct

class minf(ct.Structure):
    _fields_ = (('req_version', ct.c_short),
                ('def_zone', ct.c_short),
                ('haveshare', ct.c_short),
                ('smapi_version', ct.c_short),
                ('smapi_subversion', ct.c_short))

    # 提供了一个类来显示自己的方法(可选)
    def __repr__(self):
        return (f'minf(req_version={self.req_version}, '
                f'def_zone={self.def_zone}, '
                f'haveshare={self.haveshare}, '
                f'smapi_version={self.smapi_version}, '
                f'smapi_subversion={self.smapi_subversion})')

smapi = ct.CDLL('libsmapi.so')
# 建议定义参数类型和返回类型。
# 不要假设 ctypes 知道如何转换参数。
# 定义这些允许 ctypes 检查传递的参数类型是否兼容。
#
# 这假定一个 C 原型为 "int MsgOpenApi(struct minf*)"
smapi.MsgOpenApi.argtypes = ct.POINTER(minf),
smapi.MsgOpenApi.restype = ct.c_int

# 替代的初始化方式。
# minf() 将所有参数初始化为零。
# 提供的参数按与 _fields_ 相同的顺序分配。
m = minf(0, 2)
print(m)  # 如果未定义 m.__str__,则调用 m.__repr__()。
# 输出:
# minf(req_version=0, def_zone=2, haveshare=0, smapi_version=0, smapi_subversion=0)

if smapi.MsgOpenApi(ct.byref(m)):  # 通过引用传递
    print("Error opening library")
英文:

cstruct isn't compatible with ctypes. Use ctypes.Structure instead:

import ctypes as ct


class minf(ct.Structure):
    _fields_ = ((&#39;req_version&#39;, ct.c_short),
                (&#39;def_zone&#39;, ct.c_short),
                (&#39;haveshare&#39;, ct.c_short),
                (&#39;smapi_version&#39;, ct.c_short),
                (&#39;smapi_subversion&#39;, ct.c_short))

    # Provides a way for a class to display itself (optional)
    def __repr__(self):
        return (f&#39;minf(req_version={self.req_version}, &#39;
                f&#39;def_zone={self.def_zone}, &#39;
                f&#39;haveshare={self.haveshare}, &#39;
                f&#39;smapi_version={self.smapi_version}, &#39;
                f&#39;smapi_subversion={self.smapi_subversion})&#39;)

smapi = ct.CDLL(&#39;libsmapi.so&#39;)
# Recommend defining argument types and return type.
# Don&#39;t assume ctypes knows how to marshal your parameters.
# Defining this allows ctypes to check the types of parameters passed are compatible.
#
# This assumes a C prototype of &quot;int MsgOpenApi(struct minf*)&quot;
smapi.MsgOpenApi.argtypes = ct.POINTER(minf),
smapi.MsgOpenApi.restype = ct.c_int

# Alternative way to initialize.
# minf() would initialize all parameters to zero.
# Provided parameters are assigned in the same order as _fields_.
m = minf(0, 2)
print(m)  # Calls m.__repr__() if m.__str__ isn&#39;t defined.
# Output:
# minf(req_version=0, def_zone=2, haveshare=0, smapi_version=0, smapi_subversion=0)

if smapi.MsgOpenApi(ct.byref(m)):  # Pass by reference
    print(&quot;Error opening library&quot;)

huangapple
  • 本文由 发表于 2023年7月18日 01:45:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76706940.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定