c++ - 将复杂列表列表的元组从 C++ 返回到 Python

标签 c++ python-3.x ctypes

我有一个 PyObject* outvar 对象,它基本上构造为:

//some defs
typedef std::complex<double> Pt;
typedef std::vector<Pt> Pgon;
typedef std::vector<Pgon> Pgons;
PyObject* outvar = PyTuple_New(2);

auto outA = pgons2pylist(pA);
auto outB = pgons2pylist(pB);
PyTuple_SET_ITEM(outvar, 0, outp);
PyTuple_SET_ITEM(outvar, 1, outl);

哪里 pgons2pylist

PyObject* pgons2pylist(const Pgons& data) {
  PyObject* listObj = PyList_New( data.size() );
    for (unsigned int i = 0; i < data.size(); i++) {
        PyList_SET_ITEM(listObj, i, pgon2pylist(data[i]));
    }
    return listObj;
}

pgon2pylist是:

PyObject* pgon2pylist(const Pgon& data) {
  PyObject* listObj = PyList_New( data.size() );
    for (unsigned int i = 0; i < data.size(); i++) {
        PyList_SET_ITEM(listObj, i, PyComplex_FromDoubles(data[i].real(),data[i].imag()));
    }
    return listObj;
}

我编译它并从 py 文件运行它:

mylib = ctypes.cdll.LoadLibrary('./mylib.so')
out_data = mylib.call(some_args)

但是 out_data 总是一个整数!如何转换为 [[complex]]?

最佳答案

您构建C 代码的方式看起来更接近扩展模块 ( [Python 3]: Extending Python with C or C++ ) 而不是简单的.dll。检查[SO]: Pass str as an int array to a Python C extended function (extended using SWIG) (@CristiFati's answer)用于方法之间的比较。

然后,作为注释,您需要为导入的函数指定 argtypesrestype(这就是您获得 int).检查[SO]: Python ctypes cdll.LoadLibrary, instantiate an object, execute its method, private variable address truncated如果你不这样做可能会发生什么。

同时列出 [Python 3]: ctypes - A foreign function library for Python页面。

关于代码的一些注释:

因此,假设您有一个可用的 .dll,下面是您将如何使用它(盲目发布代码):

mylib = ctypes.pydll.LoadLibrary('./mylib.so')
outvar = ctypes.py_object.in_dll(mylib, "outvar")  # Note that you might have to declare it as extern "C", so its name doesn't get mangled

@EDIT0:

我创建了一个虚拟示例来测试是否一切正常。

dll.c:

#include <Python.h>

#if defined(_WIN32)
#  define EXPORT __declspec(dllexport)
#else
#  define EXPORT
#endif


EXPORT PyObject *tp = NULL;
EXPORT int i = 123;
EXPORT char *s = "Gainarie";
EXPORT float f = -3.14;


EXPORT void initTpl() {
    tp = PyTuple_New(2);
    PyTuple_SET_ITEM(tp, 0, PyLong_FromLong(7));
    PyTuple_SET_ITEM(tp, 1, PyLong_FromLong(-9));
}

代码.py:

#!/usr/bin/env python3

import sys
import ctypes


def main():
    dll = ctypes.PyDLL("./dll.so")
    i = ctypes.c_int.in_dll(dll, "i")
    s = ctypes.c_char_p.in_dll(dll, "s")
    f = ctypes.c_float.in_dll(dll, "f")
    dll.initTpl()
    tp = ctypes.py_object.in_dll(dll, "tp")

    print(i.value, s.value, f.value, tp.value, type(tp.value))


if __name__ == "__main__":
    print("Python {:s} on {:s}\n".format(sys.version, sys.platform))
    main()

注意事项:

  • 我只在 Win 上测试过,因为我没有在我的 Lnx VM 上传输我的文件,但这不应该是一个问题
  • 因为它仅用于演示目的,所以我不关心内存泄漏(我也没有检查是否需要 Py_XDECREF)

输出:

e:\Work\Dev\StackOverflow\q054429301>dir /b
code.py
dll.c

e:\Work\Dev\StackOverflow\q054429301>"c:\Install\x86\Microsoft\Visual Studio Community\2015\vc\vcvarsall.bat" x64

e:\Work\Dev\StackOverflow\q054429301>cl /nologo /DDLL /MD /I"c:\Install\x64\Python\Python\03.06.08\include" dll.c  /link /NOLOGO /DLL /LIBPATH:"c:\Install\x64\Python\Python\03.06.08\libs" /OUT:dll.so
dll.c
   Creating library dll.lib and object dll.exp

e:\Work\Dev\StackOverflow\q054429301>dir /b
code.py
dll.c
dll.exp
dll.lib
dll.obj
dll.so

e:\Work\Dev\StackOverflow\q054429301>"e:\Work\Dev\VEnvs\py_064_03.06.08_test0\Scripts\python.exe" code.py
Python 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018, 00:16:47) [MSC v.1916 64 bit (AMD64)] on win32

123 b'Gainarie' -3.140000104904175 (7, -9) <class 'tuple'>

关于c++ - 将复杂列表列表的元组从 C++ 返回到 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54429301/

相关文章:

python - 公开 EVP_MD_CTX 的 _hashlib.pyd 内部结构吗?

c++ - 虚继承的内部机制

python - 在我的 scrapy 蜘蛛中,我的解析模块无法工作,无法打印

python - 尽管我在 python ctypes 中设置了信号处理程序,但它不会被调用

python - 子进程 Python .. 将命令串在一起

csv - UnicodeDecodeError : 'charmap' codec can't decode byte 0x8d in position 7240: character maps to <undefined>

python - 如何保存包含指针的 ctypes 对象

c++ - 获取 IAMStreamConfig 接口(interface)失败

c++ - 如何计算文件中的零和一?

c++ - 成员函数回调