从Fortran/C调用Python函数

3

我正在编写一段Fortran代码,希望能够使用Python库中的一些特殊函数和方法。以下是Python代码:

from mpmath import *
from scipy.optimize import *

def g(A,B,t):   
   return newton(lambda x: (x - A*polylog(1.5, B*exp(-t*x))), 0.0)

在Fortran代码中,我希望传递实数值A、B、t,并返回g(A,B,t)的值(可能是复杂的)。这也可以用C语言完成。

我想提醒大家,将Python与其他语言混合使用对我来说是新事物。


2
你可能应该从这里开始 在另一个应用程序中嵌入Python(Python文档) - Thomas Orozco
请始终使用标签[tag:fortran],仅在必要时添加版本以区分您的问题。例如,您不能使用Fortran 2008,而只能使用Fortran 90。 - Vladimir F Героям слава
请参见以下链接:https://dev59.com/f3PYa4cB1Zd3GeqPjoKUhttps://dev59.com/Dnzaa4cB1Zd3GeqPSJoNhttp://stackoverflow.com/questions/20265697/how-to-return-a-value-from-a-python-callback-in-fortran-using-f2py - Vladimir F Героям слава
3
您是否意识到许多SciPy及相关库已经用Fortran和C实现了?您是否考虑过仅从Fortran中调用Fortran或C?您有从Fortran中调用C的经验吗?如果有,您可以使用Python C API。 - John Zwinck
@JohnZwinck - 我的目标是使用Python C API,然后编写一个简单的Fortran包装器。 - Bociek
1
你可能想要考虑一下并将那篇帖子标记为正确答案 ;) - Mr_Pouet
1个回答

1

解决方案

如果有人感兴趣,我已经解决了这个问题。以下链接对我很有帮助:stackoverflowyolinux

rootC.c

#include "rootC.h"
#include <Python.h>
#include <stdlib.h>

void Initialize ()
{
    Py_Initialize();
}

void Finalize ()
{
    Py_Finalize();
}

void root_(double* A, double* B, double* t, double* x)
{
    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue, *sys, *path;
    static int i;

    if (i == 0)
    {    
        ++i;
        Initialize();
        atexit(Finalize);
    }

    sys  = PyImport_ImportModule("sys");
    path = PyObject_GetAttrString(sys, "path");
    PyList_Append(path, PyString_FromString("."));

    pName = PyString_FromString("rootPY");
    pModule = PyImport_Import(pName);

    if (!pModule)
    {
        PyErr_Print();
        printf("ERROR in pModule\n");
        exit(1);
    }

    pFunc = PyObject_GetAttrString(pModule, "root");
    pArgs = PyTuple_New(3);
    PyTuple_SetItem(pArgs, 0, PyFloat_FromDouble((*A)));
    PyTuple_SetItem(pArgs, 1, PyFloat_FromDouble((*B)));
    PyTuple_SetItem(pArgs, 2, PyFloat_FromDouble((*t)));
    
    pValue = PyObject_CallObject(pFunc, pArgs);
    *x     = PyFloat_AsDouble(pValue);
}

rootC.h

#ifndef ROOT_H_
#define ROOT_H_

void Initialize();
void Finalize();
void root_(double*, double*, double*, double*);

#endif

rootPY.py

from mpmath import polylog, exp
from scipy.optimize import newton

def root(A,B,t):   
    return abs(newton(lambda x: (x - A*polylog(1.5, B*exp(-t*x))), 0.0))

rootF.F90

program main
   implicit none
   real*8 A, B, t, x
   A = 0.4d0
   B = 0.3d0
   t = 0.1d0

   call root(A,B,t,x)

   write(*,*) x

end program main

main.c

#include "rootC.h"
#include <stdio.h>

int main() 
{
    double A = 0.4, B = 0.3, t = 0.1, x = 0.0;

    root_(&A,&B,&t,&x);

    printf("A = %f, B = %f, t = %f\n", A, B, t);

    printf("x = %.15f\n", x);

    return 0;
}

Makefile
CC = gcc
FC = gfortran
CFLAGS = -I/usr/include/python2.7
LFLAGS = -L/usr/local/lib -lpython2.7 -lm

.PHONY: all clean

all: rootF main

rootF: rootF.o rootC.o
    $(FC) $^ -o $@ $(LFLAGS)

rootF.o: rootF.F90
    $(FC) -c $< -o $@

main: main.o rootC.o
    $(CC) $^ -o $@ $(LFLAGS)

main.o: main.c
    $(CC) $(CFLAGS) -c $< -o $@

rootC.o: rootC.c
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    rm -f *.o

您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Bociek
感谢这个的解决方案,问题已经解决。 - Bociek
需要注意的唯一一件事是Python对象的引用计数。 - Bociek

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接