• windows下fortran 与C++混合编程的探索


    百度后,找到相关资源,最好的一篇是:https://www.cnblogs.com/ljwan1222/p/9546244.html

    我的环境如下: windows下 VS环境,IVF环境

    例1: 基本的结构

    1. C++ 动态库结构

    (1)头文件

    #ifdef __cplusplus
    extern "C" {
    #endif
    
    extern void __stdcall MOMENT_NEW(int* a);   //子过程, 没有__stdcall前缀也可以
    extern int __stdcall AFUNC();         //函数, 没有__stdcall前缀也可以
    extern double __stdcall BFUNC(bool);
    
    //#define moment_new MOMENT_NEW       //将函数名改为小写,使用define转为大写,失败
    //#define afunc AFUNC
    //#define bfunc BFUNC
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif //F_LIB_H

    (2)cpp文件

    // moment.cpp
    void MOMENT_NEW(int* a)
    {
        a++;
    }
    
    int AFUNC()
    {
        return 10;
    }
    
    double BFUNC(bool a)
    {
        return 3;
    }

    (3)def文件

    LIBRARY f_lib
    EXPORTS
    MOMENT_NEW @1
    AFUNC @2
    BFUNC @3

    2. fortran 主程序结构

    program main
        use iso_c_binding     !这个根据资料是必要的,通过试验,可能不需要
        implicit none
    
        type(c_ptr) :: foo
    interface  f_lib1    !用一个interface引入C++库的相关内容,名称可以任意
        subroutine MOMENT_NEW(a)     !函数名必须相同,包括参数类型要对应 
        implicit none
        integer::a            !声明参数类型
        end subroutine MOMENT_NEW
    
        integer(4) function AFUNC() 
        implicit none
        end function AFUNC
        
        real(8) function BFUNC(c)
        implicit none
        logical::c
        end function BFUNC
    
        ! type(c_ptr) :: a
        end interface f_lib1
        integer(4) jd
        real(8) js
    
        call MOMENT_NEW(4)
    
        jd = AFUNC()
        js = BFUNC(.TRUE.)
        write(*,*) jd, js
    end

     例2: 使用字符串

    1. C++ 动态库结构

    (1)头文件

    extern double __stdcall BFUNC(char* str);

    (2)实现

    double BFUNC(char* str)
    {
        cout << str << endl;
        return 0.;
    }

    2. fortran主程序

        real(8) function BFUNC(str)
        implicit none
        character(100)::str     !fortran中的字符串大小是固定的
        end function BFUNC
    
        ! type(c_ptr) :: a
        end interface f_lib1
        integer(4) jd
        real(8) js
        character(100)::str;
    
        call MOMENT_NEW(4)
    
        jd = AFUNC()
        str = 'I can do it';
        js = BFUNC(str)
        write(*,*) jd, js

    例3: 使用回调

    1. C++动态库

    (1)头文件

    #pragma once
    #ifdef __cplusplus
    extern "C" {
    #endif
    
        extern void __stdcall INITMQ(void* callback, double* time);
    
        extern void __stdcall SEND_REPORT(int* type, char* data, double* time);
    
    #ifdef __cplusplus
    }
    #endif

     (2)cpp文件

     文件中,pf函数作为参数输入

    // MidWare.cpp : 定义 DLL 应用程序的导出函数。
    //
    #include "MidWare.h"
    #include <iostream>
    using namespace std;
    typedef int(*pf)(int* type, char* data, int* len,  double* time);
    pf mycb;
    void INITMQ(void* callback, double* time) { pf mycb = (pf)callback; int t = 10; char mdata[] = "data parameter"; //double time = 0.; int len = strlen(mdata); p(&t, mdata, &len, time); cout << "initmq" << endl; } void SEND_REPORT(int* type, char* data, double* time) { cout << "SEND_REPORT" << endl; cout << data << endl; cout << *time << endl; }

    2. fortran主程序

    (1) message_ware模块

    MODULE MESSAGE_WARE
        use iso_c_binding
        implicit none
      
        interface  midware
            subroutine INITMQ(callback, ntime)
            implicit none
                interface 
                    subroutine callback(cmd, dat, dlen, time)   !回调处理
                        integer::cmd
                        character::dat(100)
                        real(8)::time
                        integer::dlen
                    end subroutine callback
                end interface 
                real(8)::ntime
            end subroutine INITMQ
    
            subroutine SEND_REPORT(data_type, mdata, time)
                implicit none
                integer::data_type
                character::mdata(100)
                real(8)::time
            end subroutine SEND_REPORT
    
        end interface midware
        
    
        
        
        contains
        
        subroutine mcallback(cmd, dat, dlen, time)
            integer::cmd
            character::dat(100)
            real(8)::time
            integer::dlen
            
            print *, cmd
            !slen = LEN(dat)
            print *, dat(1:dlen)
            !print *, dat
        end subroutine mcallback
        
        
    
    END MODULE MESSAGE_WARE

    (2)主程序

        program MidWareServer
            use iso_c_binding
            use MESSAGE_WARE
            implicit none
            ! Variables
            type(c_ptr) :: a
    
            real(8)::time = 0.
            character(100)::id = 'dasdf'
            character,allocatable,dimension(:)::sdata
            logical::bool
    
            ! Body of MidWareServer
            allocate(sdata(120));
            sdata = 'ddddd'
            
            CALL INITMQ(mcallback, time)
            CALL SEND_REPORT(1, sdata, time)
            !CALL GET_REQUEST(bool, id, sdata, 2);
            print *, 'Hello World'
    
        end program MidWareServer

    新的发现是:

    (1)当字符串为参数时,需要将charater(100):: a 改为 charater::a(100), 在回调中才能使用

    (2)C++库中的字符串参数为char* 类型,fortran中参数可以使用可变长字符数组作为实参,如上面的例子中,使用了超过100长度的变长数组sdata,可以完成数据传递

    (3)fortran回调函数必须在参数中指出字符串的长度,否则无法知道字符串中有多少有效字符

      (4)回调和接口中最好使用不定长字符数组 charater::a(*)再加入字符长度,这样可以保证任意长度的字符串

  • 相关阅读:
    Mongo Windows 基本使用入门
    ASP.NET Web API 使用Swagger使用笔记
    Smtp协议与Pop3协议的简单实现
    详解boost库中的Message Queue .
    Bencode编码解析的C++实现
    pugixml使用教程
    在QT中使用Irrlicht引擎的方法与步骤
    七大查找算法
    java保留小数点两位的4种方法
    [Node] nvm 安装 node 和 npm
  • 原文地址:https://www.cnblogs.com/myboat/p/16034230.html
Copyright © 2020-2023  润新知