从 fortran 调用 c++

问题描述 投票:0回答:1

我想调用一个函数,该函数既位于 C++ 父类“inval”中,又位于 Fortran 的 C++ 派生类“SMval”中。我想要调用的函数包含在一个更大的代码中,我想将其连接到我的 Fortran。我写了以下代码(3个文件)

在library_wrapper.h中:

#include "classes.h"
#include "SMval.h"
#ifdef __cplusplus 
//Forward declarations of classes 
class inval; 
class SMval;

extern "C" { 
#endif

void* createinval_(); 
void destroyinval_(void* instance); 
void* createSMval_(); 
void destroySMval_(void* instance); 
void invalsetWrapper_(const int idx, const double val); 
void SMvalsetWrapper_(const int idx, const double val); // Declaration of the wrapper function

#ifdef __cplusplus } 
#endif

在库wrapper.cpp中:

#include "library_wrapper.h" 
#include "classes.h" 
#include "SMval.h" 
#include "Cplx.h"
#include <iostream> 
#include <string.h>

extern "C" {
void* createinval_() {
    return new inval();
}

void* createSMval_() {
    return new SMval();
}

void destroyinval_(void* instance) {
     delete static_cast<inval*>(instance);
}

void destroySMval_(void* instance) {
    delete static_cast<SMval*>(instance);
}

void invalsetWrapper_(const int idx, const double val) {
    inval obj;
    return obj.set(idx, val);
}

void SMvalsetWrapper_(const int idx, const double val) {
    SMval obj;
    return obj.set(idx, val);
}

}

最后是主要的 Fortran 77:

   PROGRAM main
   implicit none
   CALL CREATEINVAL()
   CALL CREATESMVAL()
   CALL INVALSETWRAPPER(12, 1/137.03599976)
   CALL SMVALSETWRAPPER(1, 91.1876)
   END

我正在 MAC Sonoma 上编译:

clang++ -g -std=c++11 -c library_wrapper.cpp
ld -r allothersobjectfiles.o library_wrapper.o -o combined_library.o
clang++ -shared -o liblibrary.a combined_library.o
gfortran -ffixed-line-length-none fortran.f -o main -L. -llibrary

但是我明白了

ld: Undefined symbols:
  _createinval_, referenced from:
      _MAIN__ in ccPLQP9I.o
  _createsmval_, referenced from:
      _MAIN__ in ccPLQP9I.o
  _invalsetwrapper_, referenced from:
      _MAIN__ in ccPLQP9I.o
  _smvalsetwrapper_, referenced from:
      _MAIN__ in ccPLQP9I.o
collect2: error: ld returned 1 exit status

我尝试创建一个静态库并链接它,但它仍然不起作用

c++ interface fortran
1个回答
1
投票

要尽可能正确地做到这一点,您应该使用 Fortran 的 C/Fortran 互操作性功能,基于 iso_c_binding Fortran 模块

例如,要调用

invalsetWrapper_
函数,您的 Fortran 代码应如下所示:

program main
   use iso_c_binding
   implicit none

   interface
      subroutine inval_set_wrapper(idx,val) bind(C,name="invalsetWrapper_")
         import c_int, c_double
         integer(kind=c_int), value :: idx
         real(kind=c_double), value :: val
      end subroutine
   end interface

   !...

   call inval_set_wrapper(12, 1/137.03599976d0)

end

请注意,互操作性假设使用成对的编译器(即,您应该将

gcc
gfortran
一起使用),即使它在混合编译器时通常有效(但没有任何保证)。

© www.soinside.com 2019 - 2024. All rights reserved.