2015-12-18 2 views
3

Я пишу код Fortran, и я хотел бы использовать некоторые специальные функции и методы из библиотек Python. Это код Python:Вызов функции Python из Fortran/C

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 и получить в возвращаем значение г (А, В, т) (возможно, комплекс). Это также можно сделать в C.

Я хотел бы упомянуть, что смешивание Python с другими языками - это что-то новое для меня.

+2

Вы, вероятно, следует начать здесь [Вложение Python в другом приложении (Python Docs)] (HTTPS : //docs.python.org/3.5/extending/embedding.html). –

+0

Всегда используйте тег [tag: fortran] и добавляйте версию только тогда, когда это необходимо, чтобы отличить ваш вопрос. Например, вы не можете использовать Fortran 2008, но только Fortran 90. –

+0

См. Http://stackoverflow.com/questions/17198642/callback-python-from-fortran http://stackoverflow.com/questions/21836670/how-to- expose-python-callbacks-to-fortran-modules-modules http://stackoverflow.com/questions/20265697/how-to-return-a-value-from-a-python-callback-in-fortran-using-f2py –

ответ

1

РЕШЕНИЕ

В случае, если кто-то заинтересован, я решил эту проблему. Следующие были очень полезны: stackoverflow и yolinux.

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 [email protected] $(LFLAGS) 

rootF.o: rootF.F90 
    $(FC) -c $< -o [email protected] 

main: main.o rootC.o 
    $(CC) $^ -o [email protected] $(LFLAGS) 

main.o: main.c 
    $(CC) $(CFLAGS) -c $< -o [email protected] 

rootC.o: rootC.c 
    $(CC) $(CFLAGS) -c $< -o [email protected] 

clean: 
    rm -f *.o 
+0

Неудачно это дает мне ошибку сегментации, когда я вызываю функцию дважды - в pModule = Py_Import ... – Bociek

+0

Решено благодаря [этому] (http: /stackoverflow.com/questions/34371221/segmentation-fault-when-calling-c-function-with-python-c-api-twice/34375287#34375287) – Bociek

+0

Единственное, что нужно позаботиться, это подсчет ссылок Объекты Python. – Bociek

Смежные вопросы