разрешение неуникальных символов между библиотеками-оболочками c ++ для фортрановых подпрограмм - PullRequest
0 голосов
/ 19 октября 2011

Я работаю с двумя наборами кода FORTRAN, например, codeA.f и codeB.f. В каждом наборе кода есть подпрограммы с одинаковыми именами, но выполняющие существенно разные задачи (а также общие блоки).

codeA.f:

     subroutine init
c do something here ...
     end

codeB.f:

     subroutine init
c do something else here ...
     end

Я создаю две оболочки C ++ для обеих подпрограмм (оболочка B идентична, но подкачка B для A).

wrapperA.cpp:

namespace codeA {
    extern "C"{void init_();}
    void init() {init_();}
}

wrapperA.h:

namespace codeA {
    init();
}

Затем я компилирую две оболочки в разделяемые библиотеки.

Makefile:

codeA.o : codeA.F
    g77 -fno-automatic -fPIC -O3 -c codeA.f -o codeA.o
wrapperA.o : wrapperA.cpp
    g++ -fPIC -c wrapperA.cpp -o wrapperA.o
libwrapperA.so : codeA.o wrapperA.o
    g++ -fPIC -shared -lg2c codeA.o wrapperA.o -o libwrapperA.so

Наконец, я хочу иметь возможность вызывать две разные подпрограммы из одной и той же программы.

main.cpp:

#include "wrapperA.h"
#include "wrapperB.h"
main {
  wrapperA::init();
  wrapperB::init();
}

Основная программа связана с двумя общими библиотеками-оболочками.

Makefile:

main : main.cpp
    g++ main.cpp -I. -L. -lwrapperA -lwrapperB -o main

Все компилируется и нареканий нет. Однако при запуске программы «main» команды init () выполняют то же действие, которое определяется тем, какая из библиотек-оболочек была связана с первой. Однако, если я ссылаюсь только на одну из библиотек, компоновщик жалуется на пропущенные символы.

У меня есть два вопроса по этому поводу:

a) Можно ли связать две разные подпрограммы FORTRAN, используя только пространства имен или каким-либо другим способом, аналогичным тому, что я делаю? Если так, что я делаю не так?

b) Если а) невозможно, можно ли разрешить конфликты, указав компилятору добавить символы с некоторым уникальным идентификатором при создании объектов FORTRAN (я использую gcc версии 4.1.2 20080704 (Red Hat 4.1) .2-51?))

Спасибо за понимание.

Ответы [ 2 ]

2 голосов
/ 19 октября 2011

В ваших командах компиляции показано использование g77, которое больше не поддерживается, а также подразумевает использование очень старой версии Fortran (например, FORTRAN 77).Вы также используете старую версию GCC.Если вы используете gcc и gfortran версии 4.3 или выше - предпочтительно 4.4 или выше - тогда вы можете использовать Fortran 2003 ISO C Binding для решения вашей проблемы.В коде Фортрана вы можете назначать внешне видимые имена подпрограммам с помощью опции «bind» в привязке ISO C.Просто назначьте разные имена «связывания» двум подпрограммам.Тогда они не будут конфликтовать на уровне библиотеки и компоновщика:

В одном файле Фортрана используйте

subroutine init (stuff...) bind (C, name="init_V1")

, а другой файл

subroutine init (stuff...) bind (C, name="init_V2")

, и процедуры будутбыть видимым для C, C ++, компоновщика и т. д. как init_V1 и init_V2 без конфликтов.

0 голосов
/ 20 октября 2011

Посмотрите на этот вопрос SO, который очень похож на вашу проблему: Конфликты статических и совместно используемых библиотек?

По сути, у вас есть две совместно используемые библиотеки, определяющие разные символы: wrapperA :: init () и wrapperB :: init () ;но также конфликтующие символы: _init __ ().Поэтому, когда компоновщик разрешается, он использует первый из конфликтующих символов, которые он находит.

Если вы удалите ненужную внешнюю видимость _init __ () в своих библиотеках, используя методы, приведенные в вопросе SO: http://www.gnu.org/software/gnulib/manual/html_node/Exported-Symbols-of-Shared-Libraries.html, тогда я думаю, что вы решили свою проблему.Каждый wrapper :: init () затем будет внутренне вызывать его правильно _init __ () без какого-либо конфликта.

...