gpt4 book ai didi

python - ctypes 和构建元类 : TypeError: *class* instance instead of LP_*class* instance

转载 作者:太空宇宙 更新时间:2023-11-04 04:31:36 25 4
gpt4 key购买 nike

故事:我正在使用 ctypes从 python 到 C 进行通信,反之亦然。我也在制作我也试图连接的 C 共享库。在这个开发步骤中,它只是一个简单的库,用于在深入编写代码之前测试所有概念。它是用 C++ 编写的库,使用 extern "C"公开函数,没什么特别的。我测试了具有原始参数/返回类型、指针和函数回调的函数。

现在我想传递结构。由于我是一个懒惰的程序员,我打算将 C++ 结构传递给统一的 C 表示(即简单字典和列表的组合)并将其处理给 python,后者会将其转换为真正的 python 对象(即一个字典和列表的 python 组合)。

问题:为了实现这一点,我首先在 C++ 中定义了一个模板化字典,它的实现只是为了测试,一个键值对的链表,字典拥有根。然后,对于每个需要特化的函数,该特化的 typedef 用作 C 结构。

代码看起来像这样(不是实际代码):

#include <cstdlib>

template <typename key_t, typename value_t>
struct DictNode
{
key_t key;
value_t value;
};

template <typename key_t, typename value_t>
struct Dict
{
typedef DictNode<key_t, value_t> node_t;
node_t root;
};

typedef Dict<int, char> Dict_int_char;

extern "C" Dict_int_char* example_new()
{
Dict_int_char* result;
result = (Dict_int_char*)malloc(sizeof(Dict_int_char));
return result;
}

extern "C" void example_delete(Dict_int_char* value)
{
free(value);
}

现在,在 python 中,为了避免为每个专业创建一个类,我采用了相同的方法。一个方法将为我创建给定键值类型的专用类。

代码看起来像这样(实际代码):

import types
import ctypes

# This is to provide some hiding of the module internals
# Suggestions on a more pythonic way are gladly accepted
class __Internals:
"""
Creates class to interface with a C structure comming from a
typedef'd C++ class template specialization. This method recieves
the types of the template class, creates the ctypes classes to
interface with the specialized class (which has been typedef'd)
and returns them for usage with ctypes.
"""
@staticmethod
def __DictClassCreate__(key_t, value_t):
# Foward declare the classes
class InterfaceListNode(ctypes.Structure):
pass;
class InterfaceList(ctypes.Structure):
pass;

#### NODE
# Node class
nodeType = InterfaceListNode;
# The pointer-to-node class
nodeTypePointerType = ctypes.POINTER(nodeType);
# Fields of the node class (next, key, value)
nodeType._fields_ = [("next", nodeTypePointerType),
("key", key_t),
("value", value_t) ];

# Function to create a node pointer
def nodeTypePointerCreate(cls, value=None):
if(value is None):
return nodeTypePointerType();
else:
return nodeTypePointerType(value);

# Bind the function to the node class
nodeType.pointer = types.MethodType(nodeTypePointerCreate, nodeType);

#### DICT
# Dict class
dictType = InterfaceList;
# The pointer-to-dict class
dictTypePointerType = ctypes.POINTER(dictType);
# Useful for dict to know the types of it's nodes
dictType._nodeType = nodeType;
# Fields of the dict class (root)
dictType._fields_ = [("root", ctypes.POINTER(nodeType))];

# Function to create a dict pointer
def dictTypePointerCreate(cls, value=None):
if(value is None):
return dictTypePointerType();
else:
return dictTypePointerType(value);

# Bind the function to the dict class
dictType.pointer = types.MethodType(dictTypePointerCreate, dictType);

# For debugging
print 'Inside metaclass generator'
print hex(id(nodeType));
print hex(id(dictType));

# Return just the dict class since it knows about it's node class.
return dictType;

# Create a new specialized dict<c_uint, c_char>
dictType_1 = __Internals.__DictClassCreate__(ctypes.c_uint, ctypes.c_char);
# Obtain the node type of this dict
nodeType_1 = dictType_1._nodeType;

# For debugging
print 'In Script'
print hex(id(nodeType_1));
print hex(id(dictType_1));

# Try to instance this dictionary with 1 element
#(not NULL root, NULL root.next)
dict_1 = dictType_1(nodeType_1(nodeType_1.pointer(), 0, 'a'));

运行此代码时,将显示以下输出:

python SciCamAPI.py
Inside metaclass generator
0x249c1d8L
0x249c588L
In Script
0x249c1d8L
0x249c588L
Traceback (most recent call last):
File "SciCamAPI.py", line 107, in <module>
dict_1 = dictType_1(nodeType_1(nodeType_1.pointer(), 0, 'a'));
TypeError: incompatible types, InterfaceListNode instance instead of LP_InterfaceListNode instance

从打印的输出中我可以看到我正在使用相同的元类来实例化简单字典及其节点,作为方法中生成的节点。

我用谷歌搜索了错误中附加的 LP_ 是什么,但是搜索 LP_ python 只返回线性问题求解器和 this answer .从对答案的理解来看,ctypes 正在从 nodeType_1.pointer() (最后一行)创建一个 C 风格的指针,但这就是当 node.next 被声明为 [("next", nodeTypePointerType) 时应该收到的内容,...](在 nodeType.fields=...)。所以我很迷茫。

最佳答案

引用eryksun的评论:

dictType_1.root is an LP_InterfaceListNode field, i.e. POINTER(InterfaceListNode), but you're initializing it with an InterfaceListNode instead of a pointer to one. "LP" is for "long pointer" from back in the day of segmented architectures that had near (within segment) and far/long pointers. Windows types retain this prefix even though it's no longer meaningful, such as LPVOID and LPWSTR. ctypes was initially a Windows-only package

所以我错过了将 dictType_1.root 转换为指针。将最后一行更改为:

rootNode = nodeType_1(nodeType_1.pointer(), 0, 'a');
dict_1 = dictType_1(nodeType_1.pointer(rootNode));

解决问题。

关于python - ctypes 和构建元类 : TypeError: *class* instance instead of LP_*class* instance,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35592318/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com