我正在try 在Python和C++之间进行互操作.

以下是我的测试DLL方法的C++代码:

extern "C" __declspec(dllexport) PEParserNamespace::PEParserBase& _cdecl test(PEParserNamespace::PEParserBase* base) {
    printf("the C++ function was called\n");
    base->bytes = 12345;
    return *base;
}

我try 在Python中使用它,如下所示:

import ctypes
#DataStructures.py
class PEParserBase(ctypes.Structure):
    _fields_ = [("hFile", ctypes.c_void_p),
        ("dwFileSize", ctypes.c_ulong),
        ("bytes", ctypes.c_ulong),
        ("fileBuffer",ctypes.c_void_p)]
class PEHEADER(ctypes.Structure):
    xc = 0
#FunctionWrapper.py
def testWrapper(peParserBase, _instanceDLL):
    _instanceDLL.test.argtypes = [ctypes.POINTER(PEParserBase)]
    _instanceDLL.test.restype = PEParserBase
    return _instanceDLL.test(ctypes.byref(pEParserBase))

pEParserBase = PEParserBase()
print("hallo welt")
_test = ctypes.CDLL('PeParserPythonWrapper.dll')

print(id(testWrapper(pEParserBase, _test)))
print(id(pEParserBase))

我原以为testWrapper会返回原始的PEParserBase实例,但事实并非如此--报告的id个值是不同的.C++代码不会创建PEParserBase的任何新实例或其他任何内容,所以我确信问题一定出在Python代码中.

为什么会发生这种情况,我如何修复它?

推荐答案

CPython中的id()返回Pythonctypes包装对象的地址,而不是包装对象的地址.为此,请使用ctypes.addressof().

ctypes也只理解C普通老式数据(POD)类型和 struct .它不知道C++名称空间或引用,但由于引用实际上是指针的C++语法糖,您可以使用.argtypes.restype中的指针作为替代.

下面是一个最小的例子:

test.cpp

#include <stdio.h>

namespace PEParserNamespace {
struct PEParserBase {
    void* hFile;
    unsigned long dwFileSize;
    unsigned long bytes;
    void* fileBuffer;
};
}

extern "C" __declspec(dllexport)
PEParserNamespace::PEParserBase& _cdecl test(PEParserNamespace::PEParserBase* base) {
    printf("the C++ function was called\n");
    base->bytes = 12345;
    return *base;
}

test.py

import ctypes as ct

class PEParserBase(ct.Structure):
    _fields_ = (("hFile", ct.c_void_p),
                ("dwFileSize", ct.c_ulong),
                ("bytes", ct.c_ulong),
                ("fileBuffer",ct.c_void_p))

dll = ct.CDLL('./test')
dll.test.argtypes = ct.POINTER(PEParserBase),
dll.test.restype = ct.POINTER(PEParserBase)    # Use a pointer here for the reference

base = PEParserBase()
pbase = dll.test(ct.byref(base))

print(hex(ct.addressof(base)), base.bytes)
print(hex(ct.addressof(pbase.contents)), base.bytes)  # .contents dereferences the pointer
                                                  # so we get the address of the structure
                                                  # not the address of the pointer itself.

输出:

the C++ function was called, base=00000169712ADAF0
0x169712adaf0 12345
0x169712adaf0 12345

Python相关问答推荐

线性模型PanelOLS和statmodels OLS之间的区别

如何在具有重复数据的pandas中对groupby进行总和,同时保留其他列

从webhook中的短代码(而不是电话号码)接收Twilio消息

即使在可见的情况下也不相互作用

使用FASTCGI在IIS上运行Django频道

比较两个数据帧并并排附加结果(获取性能警告)

韦尔福德方差与Numpy方差不同

C#使用程序从Python中执行Exec文件

pandas:排序多级列

使用特定值作为引用替换数据框行上的值

在pandas数据框中计算相对体积比指标,并添加指标值作为新列

matplotlib + python foor loop

Matplotlib中的字体权重

提高算法效率的策略?

Pandas在rame中在组内洗牌行,保持相对组的顺序不变,

SpaCy:Regex模式在基于规则的匹配器中不起作用

如何从数据框列中提取特定部分并将该值填充到其他列中?

替换包含Python DataFrame中的值的<;

如何将列表从a迭代到z-以抓取数据并将其转换为DataFrame?

查找数据帧的给定列中是否存在特定值