Python 到 .cpp 并通过 .so 使用 ctypes 再次返回

Python to .cpp and back again with ctypes via an .so

我正在做一些愚蠢的事情,但没有看到什么...我已将我的问题简化为以下(荒谬的)示例 - 但它突出显示了我的问题所在 - 我显然无法传递数据从 c++ 连贯地进入 and/or return。

test.cpp

extern "C"
double reflect(double inp){
    return inp;
}

以上编译为:

g++ -c -Wall - Werror -fPIC test.cpp -o testO.o
g++ -shared -o testSO.so testO.o

仅包含输出文件定义,因为我会在实际问题中使用它们

.py

import ctypes
hdl = ctypes.cdll.LoadLibrary(r"C:\Windows\path\to\testSO.so")

所以,我的 return

hdl.reflect(1)
>>> 1    (no ctypes conversion, but erm, OK)

hdl.reflect(1.1)
>>> Failure (this is expected)

hdl.reflect(ctypes.c_int(1))
>>> 1   (right well, c_int to c_double looks like it could implicitly work)

hdl.reflect(ctypes.c_float(1.1))
>>> 1006192077   (WTF?!?)

hdl.reflect(ctypes.c_double(1.2))
>>> 858993459    (WTF?!?!)

OS 是 windows 10,编译器是 minGW-W64 8.1.0,python 是 3.8 (anaconda)

我之前有 运行 个 DLL,并且我之前已经将我自己的 .c 编译成 python 模块 - 但对于我来说,我看不出我在这里做错了什么。 ....!?!

编辑:更正了拓扑排序指出的拼写错误(.so 的路径在代码中是正确的,此处缺少尾随 ")

目标文件和共享库不包含任何关于函数参数类型或 return 类型的信息,至少对于 C 链接函数是这样。

因此 ctypes 无法知道该函数应该采用 double 参数和 return 一个 double.

如果你用 ctypes.c_double 以外的任何东西作为参数调用它,你将有未定义的行为。但是您可以将参数类型设置为自动转换为正确的 ctypes 类型(见下文)。

ctypes 还假设 return 类型是 int。如果不是这种情况,您应该在调用之前正确设置 return 类型。在下文中,我还设置了参数类型,以便 ctypes 在调用中自动使用正确的类型:

reflect = hdl.reflect
reflect.argtypes = [ctypes.c_double]
reflect.restype = ctypes.c_double
reflect(1.2)