Подпрограммы Фортрана выдают ошибку «Неопределенные символы» при соединении с программой на С ++ - PullRequest
0 голосов
/ 26 марта 2019

Я пишу короткую программу для проверки вызова библиотеки fortran Stripack из c ++. Каждый из файлов c ++ и fortran успешно компилируется, но при компоновке возникают ошибки.

Код C ++ выглядит следующим образом:

#include <iostream>
#include <cmath>

#ifdef __cplusplus
extern"C" {
    #endif
    void trmesh_(int&,float[],float[],float[],int[],int[],int[],int&,int[],int[],float[],int&);
    void trlist2_(int&,int[],int[],int[],int&,int[][3],int&);
    #ifdef __cplusplus
}
#endif


int main(){

// Variables for distributing points on sphere.
  int polar = 16;
  int azimuth = 32;
  int n = polar*azimuth-azimuth+2;
  float radius=1.0;

// Define variables needed by Stripack
  float xs[n];
  float ys[n];
  float zs[n];
  int list[6*(n-2)];
  int lptr[6*(n-2)];
  int lend[6*(n-2)];
  int near[n];
  int next[n];
  float dist[n];
  int ltri[2*n-4][3];
  int lnew;
  int ier;
  int nt;

// Distribute n points on surface of unit sphere .
// xs, ys, zs store x, y, and z components pf each point position.
  zs[0] = 1;
  xs[0] = 0;
  ys[0] = 0;
  zs[n] = -1;
  xs[n] = 0;
  ys[n] = 0;
  for (int ii=1; ii<polar; ii++){
    for (int jj=0; jj<azimuth; jj++){
      zs[(ii-1)*azimuth+jj+1] = radius*cos(ii*M_PI/polar);
      xs[(ii-1)*azimuth+jj+1] = radius*sin(ii*M_PI/polar)*sin(jj*2*M_PI/azimuth);
      ys[(ii-1)*azimuth+jj+1] = radius*sin(ii*M_PI/polar)*cos(jj*2*M_PI/azimuth);
    }
  }

// Call stripack subroutines to obtain list of triangles ltri
  trmesh_(n,xs,ys,zs,list,lptr,lend,lnew,near,next,dist,ier);
  trlist2_(n,list,lptr,lend,nt,ltri,ier);

// Output list of triangles
  for (int ii =0; ii<n; ii++){
    std::cout << ltri[ii][0] << " " << ltri[ii][1] << " " << ltri[ii][2] << std::endl;
  }

}

Я компилирую файлы следующим образом:

ifort -c stripack.f90
clang++ -c -O0 -std=c++11 -c -o main.o main.cpp -g
clang++ -o main stripack.o main.o

Первые две компиляции работают нормально, но последняя дает следующие результаты. Кажется, что подпрограммы в файле fortran не могут найти стандартные функции fortran? Я попытался с Gfortran, и та же проблема возникает. Будем весьма благодарны за любые предложения относительно того, что происходит.

Undefined symbols for architecture x86_64:
  "___libm_sse2_sincos", referenced from:
      _trplot_ in stripack.o
      _vrplot_ in stripack.o
  "___svml_sincos2", referenced from:
      _trans_ in stripack.o
  "_for_date_and_time", referenced from:
      _timestamp_ in stripack.o
  "_for_stop_core", referenced from:
      _trmesh_ in stripack.o
      _addnod_ in stripack.o
  "_for_trim", referenced from:
      _timestamp_ in stripack.o
  "_for_write_seq_fmt", referenced from:
      _delnod_ in stripack.o
      _edge_ in stripack.o
      _timestamp_ in stripack.o
      _trlprt_ in stripack.o
      _trmesh_ in stripack.o
      _addnod_ in stripack.o
      _trplot_ in stripack.o
      ...
  "_for_write_seq_fmt_xmit", referenced from:
      _delnod_ in stripack.o
      _edge_ in stripack.o
      _timestamp_ in stripack.o
      _trlprt_ in stripack.o
      _trmesh_ in stripack.o
      _addnod_ in stripack.o
      _trplot_ in stripack.o
      ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

1 Ответ

1 голос
/ 27 марта 2019

Я покажу, что это проблема со ссылкой на пример, вам нужно немного больше изучить, чтобы решить эту проблему, так как предоставленная вами информация не является полной.

!fortran code, named as x.f90
subroutine testFDLL(str, n) bind(c, name='testFDLL_as_C')
    use ISO_C_BINDING
    integer(c_int), value :: n
    character(kind=c_char), intent(in) :: str(n)
    write(6,*)" Hello FORTRAN : let us do something ...",str
    return
end

Следующий демонстрационный код C используется для демонстрации (в основном вы уже получили C ++).

//c named as y.c
#include <stdio.h>
#include <string.h>

int main()
{
    void testFDLL_as_C(char *str, int n);
    char str[] = "Hello from C";
    testFDLL_as_C(str, strlen(str));
    return 0;
}

Если вы компилируете и ссылаетесь, используйте следующее

ifort -c x.f90
gcc y.c x.o -W -Wall 

Зависит от версии ifort и ОС, должно появиться сообщение об ошибке, похожее на следующее

x.o: In function `testFDLL_as_C':
x.f90:(.text+0x42): undefined reference to `for_write_seq_lis'
x.f90:(.text+0x74): undefined reference to `for_write_seq_lis_xmit'
collect2: error: ld returned 1 exit status

Вы можете заметить, что шаблон неопределенного имени ссылки похож на ваш, если вы связываетесь с

gcc y.c x.o -W -Wall -L/path/to/your/ifort_lib -lifcore -ldl

Проблема должна быть решена.В зависимости от того, какую функцию FORTRAN вы использовали, вам может понадобиться связать еще несколько библиотек ifort.В этой части нужно провести некоторое исследование и выяснить.

...