从Fortran项目中使用的C ++静态库重新加载python模块的问题

时间:2018-02-10 05:49:24

标签: python c++ fortran

我正在尝试在Windows 64位上使用VS2010链接Fortran | C / C ++ | Python。我有一个用Fortran编写的主代码。从那个代码我调用一个C ++函数,之后我调用一个Python函数来进一步做一些工作。这是我的代码的简化版本:

!Fmain.f90
PROGRAM fmain
IMPLICIT NONE
INTERFACE
SUBROUTINE Call_NN(input_array, output_array) BIND(C, name='Call_NN')
USE, INTRINSIC :: iso_c_binding
IMPLICIT NONE
REAL(C_DOUBLE), INTENT(IN), DIMENSION(*) :: input_array
REAL(C_DOUBLE), INTENT(INOUT), DIMENSION(*) :: output_array
END SUBROUTINE
END INTERFACE

REAL*8, DIMENSION(0:2) :: input_array, output_array
REAL :: b
INTEGER :: i

do i = 1, 3
input_array = 0.01d0
output_array = 0.d0
call Call_NN(input_array, output_array)
enddo

END

C ++静态库如下:

//Csub.cpp
#include <Python.h>
#include <cassert>
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <array>
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <assert.h>
#include <stdlib.h>

using namespace std;


extern "C" void Call_NN(array<double,3> input_array, array<double,3> output_array)
    {    
        // Initialize the Python interpreter.
        Py_Initialize();

        // Variables Declaration
        float result  = 0; 
        float result1 = 0;
        float result2 = 0;
        float result3 = 0;
        float value1  = 0;
        float value2  = 0;
        float value3  = 0;

        // Create some Python objects that will later be assigned values.
        PyObject *pName, *pModule, *pDict, *pFunc, *pArgs, *pValue1, *pValue2, *pValue3;
        PyObject *pT1, *pT2, *pT3;

        // Convert the file name to a Python string.
        const char* filename = "module"; 
        pName = PyString_FromString(filename); 
        if (pName == nullptr)
        {
            PyErr_Print();
            std::exit(1);
        }

        // Import the file as a Python module.
        pModule = PyImport_Import(pName); 
        if (pModule == nullptr)
        {
            PyErr_Print();
            std::exit(1);
        }

        // Create a dictionary for the contents of the module.
        pDict = PyModule_GetDict(pModule);
        if (pDict == nullptr)
        {
            PyErr_Print();
            std::exit(1);
        }

        // Get the add method from the dictionary.
        pFunc = PyDict_GetItemString(pDict, "NN");
        if (pFunc == nullptr)
        {
            PyErr_Print();
            std::exit(1);
        }

        // Create a Python tuple to hold the arguments to the method.
        pArgs = PyTuple_New(3);
        if (pArgs == nullptr)
        {
            PyErr_Print();
            std::exit(1);
        }

        // Convert 3 to a Python integer.
        value1 = input_array[0];
        value2 = input_array[1];
        value3 = input_array[2];
        pValue1 = PyFloat_FromDouble(value1);
        pValue2 = PyFloat_FromDouble(value2);
        pValue3 = PyFloat_FromDouble(value3);

        // Set the Python int as the first and second arguments to the method.
        PyTuple_SetItem(pArgs, 0, pValue1);
        PyTuple_SetItem(pArgs, 1, pValue2);
        PyTuple_SetItem(pArgs, 2, pValue3);

        // Call the function with the arguments.
        PyObject* pResult = PyObject_CallObject(pFunc, pArgs);

        // Print a message if calling the method failed.
        if (pResult == NULL)
            printf("Calling the add method failed.\n");

        // Convert the result to a long from a Python object.
        //result = PyFloat_AsDouble(pResult);
        pT1 = PyTuple_GetItem(pResult, 0);
        pT2 = PyTuple_GetItem(pResult, 1);
        pT3 = PyTuple_GetItem(pResult, 2);

        // Convert output to float
        result1 = PyFloat_AsDouble(pT1);
        result2 = PyFloat_AsDouble(pT2);
        result3 = PyFloat_AsDouble(pT3);
        output_array[0] = result1;
        output_array[1] = result2;
        output_array[2] = result3;

        // Destroy the Python interpreter.
        Py_Finalize();

    }

Python模块定义为:

# module.py
import sys
import numpy as np
import pandas as pd
import pickle
from sklearn.externals import joblib

def NN(a,b,c,):
    X_array = np.array([a, b, c])
    X = pd.DataFrame(X_array).transpose()
    clf = joblib.load('SavedNeuralNetwork.pkl')
    y = clf.predict(X)
    y = pd.DataFrame(y).transpose()
    y_array = pd.DataFrame.as_matrix(y)
    i = y_array.item(0) 
    j = y_array.item(1)
    k = y_array.item(2)
    output = (i, j, k)
    return i, j, k 

在第一次迭代时,程序工作正常,但在第二次迭代中,我在行处得到一个未处理的异常:

pModule = PyImport_Import(pName);

特别是:

Unhandled exception at 0x00000001800db3ec in Fmain.exe: 0xC0000005: Access 
violation writing location 0x0000000000000002.

为什么会这样?我尝试在第一次迭代后重新加载python模块,但同样的事情发生了。对此有任何建议或其他意见,我们非常感谢。

0 个答案:

没有答案