<p>正如OP在评论@Armin Rigo的答案时指出的,正确的方法是使用包装器函数。此外,正如在原问题的注释(我)中所提到的,这也是C++和FORTRAN的可能。然而,在这三种语言中实现这一点的方法并不明显。因此,这个答案为每种语言提供了一个工作示例。在</p>
<P>假设你有一个C/C++ +FORTRAN程序,它采用标量复杂的参数。然后,您需要编写一个包装程序,它接受两个浮点/双精度(实数和虚部),将它们组合成一个复数,然后调用原始过程。显然,这可以扩展到复数数组,但现在让我们用一个复数保持简单。在</p>
<h2>C</h2>
<p>例如,假设您有一个C函数来打印格式化的复数。所以我们有<code>my_complex.c</code>:</p>
<pre><code>#include <stdio.h>
#include <complex.h>
void print_complex(double complex z)
{
printf("%.1f + %.1fi\n", creal(z), cimag(z));
}
</code></pre>
<p>然后我们必须添加一个包装器函数(在同一个文件的末尾),如下所示:</p>
^{pr2}$
<p>用通常的方法将其编译到库中:</p>
<pre><code>gcc -shared -fPIC -o my_complex_c.so my_complex.c
</code></pre>
<p>然后从Python调用wrapper函数:</p>
<pre><code>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))
</code></pre>
<H1> C++ +/H1>
<P> C++中的相同的东西有点不太灵活,因为需要定义一个^ {< CD2>}接口以避免名称的篡改,并且我们需要用Python处理该类(既按^ <a href="https://stackoverflow.com/questions/145270/calling-c-c-from-python">this SO Q&A</a>)。在</p>
<p>所以,现在我们有了<code>my_complex.cpp</code>(我已经在其中添加了包装函数):</p>
<pre><code>#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);
}
};
</code></pre>
<p>我们还需要添加一个<code>extern "C"</code>接口(在同一个文件的末尾),如下所示:</p>
<pre><code>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);
}
}
</code></pre>
<p>按常规方法编译到库中:</p>
<pre><code>g++ -shared -fPIC -o my_complex_cpp.so my_complex.cpp
</code></pre>
<p>并从Python调用包装器:</p>
<pre><code>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)
</code></pre>
<h2>Fortran语言</h2>
<p>最后在Fortran中,我们在<code>my_complex.f90</code>中有一个原始子例程:</p>
<pre><code>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
</code></pre>
<p>我们在其中添加了包装器函数(在同一文件的末尾):</p>
<pre><code>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
</code></pre>
<p>然后按常规方法编译到库中:</p>
<pre><code>gfortran -shared -fPIC -o my_complex_f90.so my_complex.f90
</code></pre>
<p>并从Python调用(注意指针的用法):</p>
<pre><code>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))
</code></pre>