【问题标题】:Pass a pointer to dynamically assigned variable to a function to deleting将指向动态分配变量的指针传递给要删除的函数
【发布时间】:2021-07-28 22:10:18
【问题描述】:

libtestm.dll 代码

#pragma once
#define EXPORT extern "C" __declspec(dllexport)
#include <iostream>
#include <vector>

class TestValue
{
public:
    std::vector<int> v;
    TestValue()
    {
        for (size_t i = 0; i < 10; i++)
        {
            v.push_back(i);
        }
    }
    ~TestValue()
    {
        std::cout << "Deteled Test Value" << std::endl;
    }
};

EXPORT TestValue *TestReturn()
{
    return new TestValue();
}

EXPORT size_t TestData(TestValue *pt, int **array)
{
    *array = pt->v.data();
    return pt->v.size();
}

EXPORT void TestDelete(TestValue *pt)
{
    if(pt)
    {
        delete pt;
    }
}

TestLib.py

import os, sys
from ctypes import *
import Libs.Utils as u

__dllname__: str = 'libtestm.dll'

__dllfile__: str = None
__dll__: cdll = None
__dllfile__, __dll__ = u.FindLoadDll(__dllname__, __file__) # get dll from this method

if __name__ == "__main__":
    v = __dll__.TestReturn()
    __dll__.TestDelete(v)

运行此代码时的控制台输出

Deteled Test Value
Traceback (most recent call last):
  File "d:\MyProjects\GitRepo\CodePython\Dlls\TestLib.py", line 31, in <module>
    __dll__.TestDelete(v)
OSError: exception: access violation reading 0x00000000A20E2490

c++标准库与python的ctypes一起使用很困难,所以我尝试通过将它包装在一个类中来使用它。成功释放指向动态分配变量的指针,但发生错误。请让我知道我错了什么。谢谢。

【问题讨论】:

    标签: python pointers ctypes


    【解决方案1】:

    这是大多数ctypes 用户的标准错误。 ctypes 如果未指定,则假定参数类型,通常是 c_int 或参数指针,c_int 用于返回类型。由于 TestValue* 是 64 位的,c_int 的返回值是 32 位并截断它。解决方案是养成始终为使用的每个函数指定.argtypes.restype 的习惯:

    test.cpp:

    #pragma once
    #define EXPORT extern "C" __declspec(dllexport)
    #include <iostream>
    #include <vector>
    
    class TestValue {
    public:
        std::vector<int> v;
        TestValue() {
            for (int i = 0; i < 10; i++)
                v.push_back(i);
        }
        ~TestValue() {
            std::cout << "Deleted Test Value" << std::endl;
        }
    };
    
    EXPORT TestValue *TestReturn() {
        return new TestValue();
    }
    
    EXPORT size_t TestData(TestValue *pt, int **array) {
        *array = pt->v.data();
        return pt->v.size();
    }
    
    EXPORT void TestDelete(TestValue *pt) {
        if(pt)
            delete pt;
    }
    

    test.py:

    from ctypes import *
    
    dll = CDLL('./test')
    dll.TestReturn.argtypes = ()
    dll.TestReturn.restype = c_void_p
    dll.TestData.argtypes = c_void_p,POINTER(POINTER(c_int))
    dll.TestData.restype = c_size_t
    dll.TestDelete.argtypes = c_void_p,
    dll.TestDelete.restype = None
    
    v = dll.TestReturn()
    data = POINTER(c_int)()
    size = dll.TestData(v,byref(data))
    print(data[:size])
    dll.TestDelete(v)
    

    输出:

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Deleted Test Value
    

    【讨论】:

    • 非常感谢!尽管我跳过了 64 位配置,但更感谢您的完整解释。正如你所说,我是 C++ 和 Python 的初学者。我需要多学习。再次感谢您的完美回答。
    猜你喜欢
    • 2013-10-30
    • 1970-01-01
    • 2013-04-14
    • 2013-07-21
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多