Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/155.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python在访问从ctypes返回的结构中的指针时崩溃_Python_C++_C_Ctypes - Fatal编程技术网

Python在访问从ctypes返回的结构中的指针时崩溃

Python在访问从ctypes返回的结构中的指针时崩溃,python,c++,c,ctypes,Python,C++,C,Ctypes,我试图访问Python中此函数返回的树: TokenTreeNode* generateTokenTree(const wchar_t** tokens, const unsigned int tokenCount, const BlockToken* blockTokens, const unsigned int blockTokenCount); TokenTreeNode的定义: typedef struct tree_node_struct { wchar_t* token;

我试图访问Python中此函数返回的树:

TokenTreeNode* generateTokenTree(const wchar_t** tokens, const unsigned int tokenCount, const BlockToken* blockTokens, const unsigned int blockTokenCount);
TokenTreeNode的定义:

typedef struct tree_node_struct {
    wchar_t* token;
    size_t childCount;
    struct tree_node_struct* parent;
    struct tree_node_struct** children;
} TokenTreeNode;
BlockToken的定义:

typedef struct {
    const wchar_t* begin;
    const wchar_t* end;
} BlockToken;
下面是相应ctypes python接口的代码:

import ctypes
from typing import List

class CBlockToken(ctypes.Structure):
    _fields_ = [('begin', ctypes.c_wchar_p),
                ('end',   ctypes.c_wchar_p)]

class CTokenTreeNode(ctypes.Structure):
    _fields_ = [('token',      ctypes.c_wchar_p),
                ('childCount', ctypes.c_size_t),
                ('parent',     ctypes.POINTER('CTokenTreeNode')),
                ('children',   ctypes.POINTER(ctypes.POINTER('CTokenTreeNode')))]

def generate_token_tree(tokens: List[str], blockTokens: List[CBlockToken]) -> CTokenTreeNode:
    nativelib = ctypes.WinDLL(source_path + '\\nativelib\\x64\\Release\\nativelib.dll')

    generateTokenTree = nativelib.generateTokenTree
    generateTokenTree.argtype = [
        ctypes.POINTER(ctypes.c_wchar_p),
        ctypes.c_uint,
        ctypes.POINTER(CBlockToken),
        ctypes.c_uint
    ]
    generateTokenTree.restype = ctypes.POINTER(CTokenTreeNode)

    c_arg_tokens             = (ctypes.c_wchar_p * len(tokens))(*tokens)
    c_arg_token_count        = len(tokens)
    c_arg_block_tokens       = (CBlockToken * len(blockTokens))(*blockTokens)
    c_arg_block_tokens_count = len(blockTokens)
    
    root_node = generateTokenTree(c_arg_tokens,
                                  c_arg_token_count,
                                  c_arg_block_tokens,
                                  c_arg_block_tokens_count)

    return root_node.contents
当我试图访问返回的根节点的子节点时,python崩溃

>>> test_tokens  = ['var', 'test', '=', '"', 'string', '"']
>>> block_tokens = [parser.CBlockToken('"', '"')]
>>> root_node = parser.generate_token_tree(test_tokens, block_tokens)
>>> root_node.childCount
4
>>> root_node.children[0].contents

python crashes

如果我在C++中访问生成的树,一切都会按预期运行。对我来说,问题似乎是由于某种原因,python不允许访问外部库分配的内存。然而,我不知道如何修复甚至调试这个问题

编辑:根据@MilesBudnek的建议更改了TreeTokenNode.childCount的类型

编辑2: 以下是根据调试器在generateTokenTreeNode()末尾的树的内存布局:

-       rootNode->children,10   0x000001e3c7454250 {0x000001e3c74544f0 {token=0x000001e3c7456b30 L"var" childCount=0 parent=0x000001e3c7454a90 {...} ...}, ...} tree_node_struct *[10]
+       [0] 0x000001e3c74544f0 {token=0x000001e3c7456b30 L"var" childCount=0 parent=0x000001e3c7454a90 {token=0x0000000000000000 <NULL> ...} ...}   tree_node_struct *
+       [1] 0x000001e3c74547f0 {token=0x000001e3c74565e0 L"test" childCount=0 parent=0x000001e3c7454a90 {token=0x0000000000000000 <NULL> ...} ...}  tree_node_struct *
+       [2] 0x000001e3c7454130 {token=0x000001e3c537d0e0 L"=" childCount=0 parent=0x000001e3c7454a90 {token=0x0000000000000000 <NULL> ...} ...} tree_node_struct *
-       [3] 0x000001e3c7454d30 {token=0x000001e3c7456360 L"\"\"" childCount=1 parent=0x000001e3c7454a90 {token=0x0000000000000000 <NULL> ...} ...}  tree_node_struct *
    -       children    0x000001e3c74569f0 {0x000001e3c7454df0 {token=0x000001e3c74567c0 L"string" childCount=0 parent=0x000001e3c7454d30 {...} ...}}   tree_node_struct * *
    -           0x000001e3c7454df0 {token=0x000001e3c74567c0 L"string" childCount=0 parent=0x000001e3c7454d30 {token=...} ...}  tree_node_struct *
        +       token   0x000001e3c74567c0 L"string"    wchar_t *
        childCount  0   unsigned __int64
        +       parent  0x000001e3c7454d30 {token=0x000001e3c7456360 L"\"\"" childCount=1 parent=0x000001e3c7454a90 {token=0x0000000000000000 <NULL> ...} ...}  tree_node_struct *
        +       children    0x0000000000000000 {???}    tree_node_struct * *
-rootNode->children,10 0x000001e3c7454250{0x000001e3c74544f0{token=0x000001e3c7456b30 L“var”childCount=0 parent=0x000001e3c7454a90{…}…},}树节点结构*[10]
+[0]0x000001e3c74544f0{token=0x000001e3c7456b30 L“var”childCount=0 parent=0x000001e3c7454a90{token=0x0000000000000000…}}树节点结构*
+[1]0x000001e3c74547f0{token=0x000001e3c74565e0 L“测试”childCount=0父节点=0x000001e3c7454a90{token=0x0000000000000000…}树节点结构*
+[2]0x000001e3c7454130{token=0x000001e3c537d0e0 L“=”childCount=0 parent=0x000001e3c7454a90{token=0x0000000000000000…}}树\u节点\u结构*
-[3]0x000001e3c7454d30{token=0x000001e3c7456360 L“\”\”childCount=1父节点=0x000001e3c7454a90{token=0x0000000000000000…}}树节点结构*
-子项0x000001e3c74569f0{0x000001e3c7454df0{token=0x000001e3c74567c0 L“string”childCount=0 parent=0x000001e3c7454d30{…}}}树节点结构**
-0x000001e3c7454df0{token=0x000001e3c74567c0 L“string”childCount=0 parent=0x000001e3c7454d30{token=…}…}树节点结构*
+令牌0x000001e3c74567c0 L“字符串”wchar\u t*
childCount 0无符号\uuuu int64
+父节点0x000001e3c7454d30{token=0x000001e3c7456360 L“\”\”childCount=1父节点0x000001e3c7454a90{token=0x0000000000000000…}}树节点结构*
+子项0x0000000000000000{???}树节点结构**

这里的函数是从python代码调用的,我们可以看到,在python访问数据结构之前,内存布局是正确的。如果尝试读取根节点的子节点,则会发生访问冲突。

CTokenTreeNode
childCount
字段可能应该是
ctypes.c\u size\u t
,而不是
c\u uint
unsigned int
通常是4个字节,而
size\u t
通常是8个字节。@MilesBudnek我改变了这一点,不幸的是它没有任何区别。一个错误是generateTokenTree.argtypes。检查。另外,
('parent',ctypes.POINTER('CTokenTreeNode'),
在CTokenTreeNode周围没有引号
CTokenTreeNode
childCount
字段可能应该是
ctypes.c\u size\u t
,而不是
c\u uint
unsigned int
通常是4个字节,而
size\u t
通常是8个字节。@MilesBudnek我改变了这一点,不幸的是它没有任何区别。一个错误是generateTokenTree.argtypes。检查。另外,
('parent',ctypes.POINTER('CTokenTreeNode'),
在CTokenTreeNode周围没有引号!