2024-06-26 00:03:47 发布
网友
这可能有点愚蠢,但我尝试使用ctypes调用一个函数,该函数接收一个复杂的向量作为参数。但在ctypes中没有类c\u复合体。 有人知道怎么解决这个问题吗?在
编辑:我指的是python的cype,以防有其他的cype。。。。在
正如OP在评论@Armin Rigo的答案时指出的,正确的方法是使用包装器函数。此外,正如在原问题的注释(我)中所提到的,这也是C++和FORTRAN的可能。然而,在这三种语言中实现这一点的方法并不明显。因此,这个答案为每种语言提供了一个工作示例。在
假设你有一个C/C++ +FORTRAN程序,它采用标量复杂的参数。然后,您需要编写一个包装程序,它接受两个浮点/双精度(实数和虚部),将它们组合成一个复数,然后调用原始过程。显然,这可以扩展到复数数组,但现在让我们用一个复数保持简单。在
例如,假设您有一个C函数来打印格式化的复数。所以我们有my_complex.c:
my_complex.c
#include <stdio.h> #include <complex.h> void print_complex(double complex z) { printf("%.1f + %.1fi\n", creal(z), cimag(z)); }
然后我们必须添加一个包装器函数(在同一个文件的末尾),如下所示:
用通常的方法将其编译到库中:
gcc -shared -fPIC -o my_complex_c.so my_complex.c
然后从Python调用wrapper函数:
from ctypes import CDLL, c_double c = CDLL('./my_complex_c.so') c.print_complex_wrapper.argtypes = [c_double, c_double] z = complex(1.0 + 1j * 2.0) c.print_complex_wrapper(c_double(z.real), c_double(z.imag))
C++中的相同的东西有点不太灵活,因为需要定义一个^ {< CD2>}接口以避免名称的篡改,并且我们需要用Python处理该类(既按^ this SO Q&A)。在
所以,现在我们有了my_complex.cpp(我已经在其中添加了包装函数):
my_complex.cpp
#include <stdio.h> #include <complex> class ComplexPrinter { public: void printComplex(std::complex<double> z) { printf("%.1f + %.1fi\n", real(z), imag(z)); } void printComplexWrapper(double z_real, double z_imag) { std::complex<double> z(z_real, z_imag); printComplex(z); } };
我们还需要添加一个extern "C"接口(在同一个文件的末尾),如下所示:
extern "C"
extern "C" { ComplexPrinter* ComplexPrinter_new() { return new ComplexPrinter(); } void ComplexPrinter_printComplexWrapper(ComplexPrinter* printer, double z_real, double z_imag) { printer->printComplexWrapper(z_real, z_imag); } }
按常规方法编译到库中:
g++ -shared -fPIC -o my_complex_cpp.so my_complex.cpp
并从Python调用包装器:
from ctypes import CDLL, c_double cpp = CDLL('./my_complex_cpp.so') cpp.ComplexPrinter_printComplexWrapper.argtypes = [c_double, c_double] class ComplexPrinter: def __init__(self): self.obj = cpp.ComplexPrinter_new() def printComplex(self, z): cpp.ComplexPrinter_printComplexWrapper(c_double(z.real), c_double(z.imag)) printer = ComplexPrinter() z = complex(1.0 + 1j * 2.0) printer.printComplex(z)
最后在Fortran中,我们在my_complex.f90中有一个原始子例程:
my_complex.f90
subroutine print_complex(z) use iso_c_binding, only: c_double_complex implicit none complex(c_double_complex), intent(in) :: z character(len=16) :: my_format = "(f4.1,a3,f4.1,a)" print my_format, real(z), " + ", aimag(z), "i" end subroutine print_complex
我们在其中添加了包装器函数(在同一文件的末尾):
subroutine print_complex_wrapper(z_real, z_imag) bind(c, name="print_complex_wrapper") use iso_c_binding, only: c_double, c_double_complex implicit none real(c_double), intent(in) :: z_real, z_imag complex(c_double_complex) :: z z = cmplx(z_real, z_imag) call print_complex(z) end subroutine print_complex_wrapper
然后按常规方法编译到库中:
gfortran -shared -fPIC -o my_complex_f90.so my_complex.f90
并从Python调用(注意指针的用法):
from ctypes import CDLL, c_double, POINTER f90 = CDLL('./my_complex_f90.so') f90.print_complex_wrapper.argtypes = [POINTER(c_double), POINTER(c_double)] z = complex(1.0 + 1j * 2.0) f90.print_complex_wrapper(c_double(z.real), c_double(z.imag))
如果c_complex是一个c结构,并且您在文档或头文件中有的定义,则可以利用ctypes来组合兼容的类型。也有可能,尽管可能性不大,但c\u complex是ctypes已经支持的类型的typdef。在
需要更多的信息来提供更好的答案。。。在
使用两次c趶double或c_float,一次用于实数,一次用于假想。 例如:
from ctypes import c_double, c_int dimType = c_int * 1 m = dimType(2) n = dimType(10) complexArrayType = (2 * c_double) * ( n * m ) complexArray = complexArrayType() status = yourLib.libcall(m,n,complexArray)
在库端(fortran示例):
正如OP在评论@Armin Rigo的答案时指出的,正确的方法是使用包装器函数。此外,正如在原问题的注释(我)中所提到的,这也是C++和FORTRAN的可能。然而,在这三种语言中实现这一点的方法并不明显。因此,这个答案为每种语言提供了一个工作示例。在
假设你有一个C/C++ +FORTRAN程序,它采用标量复杂的参数。然后,您需要编写一个包装程序,它接受两个浮点/双精度(实数和虚部),将它们组合成一个复数,然后调用原始过程。显然,这可以扩展到复数数组,但现在让我们用一个复数保持简单。在
C
例如,假设您有一个C函数来打印格式化的复数。所以我们有
my_complex.c
:然后我们必须添加一个包装器函数(在同一个文件的末尾),如下所示:
^{pr2}$用通常的方法将其编译到库中:
然后从Python调用wrapper函数:
C++ +/H1>
C++中的相同的东西有点不太灵活,因为需要定义一个^ {< CD2>}接口以避免名称的篡改,并且我们需要用Python处理该类(既按^ this SO Q&A)。在
所以,现在我们有了
my_complex.cpp
(我已经在其中添加了包装函数):我们还需要添加一个
extern "C"
接口(在同一个文件的末尾),如下所示:按常规方法编译到库中:
并从Python调用包装器:
Fortran语言
最后在Fortran中,我们在
my_complex.f90
中有一个原始子例程:我们在其中添加了包装器函数(在同一文件的末尾):
然后按常规方法编译到库中:
并从Python调用(注意指针的用法):
如果c_complex是一个c结构,并且您在文档或头文件中有的定义,则可以利用ctypes来组合兼容的类型。也有可能,尽管可能性不大,但c\u complex是ctypes已经支持的类型的typdef。在
需要更多的信息来提供更好的答案。。。在
使用两次c趶double或c_float,一次用于实数,一次用于假想。 例如:
在库端(fortran示例):
^{pr2}$相关问题 更多 >
编程相关推荐