======Динамическая загрузка библиотек======
На данной странице описаны некоторые технологии (приемы программирования), которые используются в текущем проекте.
Под динамической загрузкой разделяемой библиотеки понимается загрузка исполняемого кода, находящегося в библиотеке, во время выполнения программы. Данный подход позволяет компилировать функции на языке //Fortran// в отдельные разделяемые библиотеки и затем вызывать их из языка //C++//.
=====Типы данных=====
Fortran имеет... FIXME
=====Разница в передаче аргументов=====
//Fortran// передает аргументы в подпрограммы по ссылке (т.е по имени). //C++// передает данные по значению.
=====DLL and Shared library=====
Явная привязка (загрузка) библиотек в //Windows// может быть выполнена с помощью //WinAPI//-функций
* //LoadLibrary//,
* //GetProcAddress//,
* //FreeLibrary//.
На //Linux// или //Solaris// явное связывание может быть сделано с помощью //POSIX//-функций
* //dlopen//,
* //dlsym//,
* //dlclose//.
====Загрузка Fortran-библиотеки====
Исходный код библиотеки общий для //Windows// и //Unix//.
C ex1.f - FORTRAN file for example 1
FUNCTION FOO2(X) RESULT (R)
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'FOO2'::FOO2
REAL X
REAL :: R
R = X * 2
END FUNCTION
SUBROUTINE FOO
!DEC$ ATTRIBUTES DLLEXPORT, ALIAS:'FOO'::FOO
REAL :: R
R = 20
print *,"R=",R
END SUBROUTINE
===Загрузка динамической Fortran-библиотеки в Windows===
Средствами //Visual Studio 2008 (2005)// и //Intel Fortran Visual Studio Integration// создаем динамическую библиотеку {{:WinCppCallFortran.zip|Проект VS 2008}}.
// ex1win.cpp - Test file for passing a single real
// argument to a F77 function in a dll
#include
#include
typedef void (*SUBROUTINE)(void);
SUBROUTINE FOO;
typedef float (* FUNCTION)(float&);
FUNCTION FOO2 = NULL;
int main()
{
HINSTANCE hDll = LoadLibrary("ex1.dll");
if(hDll==NULL)
{
printf("Error load dll!");
return 1;
}
FOO = (SUBROUTINE)GetProcAddress(hDll, "FOO"); //ВНИМАНИЕ! Экспортируемые функции могут содеражть символ "_" в конце т.е foo_
if(FOO==NULL)
{
printf("Error load function!");
return 1;
}
FOO();
FOO2 = (FUNCTION)GetProcAddress(hDll, "FOO2"); //ВНИМАНИЕ! Экспортируемые функции могут содеражть символ "_" в конце т.е foo_
if(FOO==NULL)
{
printf("Error load function!");
return 1;
}
float x = 1.2f;
float y = 0.0f;
y = FOO2(x);
std::cout << "y = FOO2(" << x << ") = "
<< y << std::endl;
FreeLibrary(hDll);
return 0;
}
===Загрузка разделяемой Fortran-библиотеки в Unix===
Для компиляции //Fortran//-части используется компилятор //GFortran//, //C++//-части --- //GCC//.
Ключи компиляторов:
gfortran -shared -fPic ex1.f -o ex1.so
gcc -o ex1lnx ex1lnx.cpp -ldl
// ex1lnx.cpp - Test file
// real argument to a F77 function in a dll
#include
#include
typedef void (*SUBROUTINE)(void);
SUBROUTINE FOO = NULL;
typedef float (*FUNCTION)(float&);
FUNCTION FOO2 = NULL;
int main()
{
void *hDll = dlopen("./ex1.so", RTLD_NOW);
if(hDll == NULL)
{
std::cout << "Error load library!";
return 1;
}
FOO = (SUBROUTINE)dlsym(hDll, "foo_");
if(FOO == NULL)
{
std::cout << "Error load subroutine!";
return 1;
}
FOO2 = (FUNCTION)dlsym(hDll,"foo2_");
if(FOO2 == NULL)
{
std::cout << "Error load function!";
return 1;
}
FOO();
float x = 1.2f;
float y = 0.0f;
y = FOO2(x);
std::cout << "y = foo(" << x << ") = "
<< y << std::endl;
dlclose(hDll);
return 0;
}
====Динамическая загрузка C++-библиотеки=====
===Загрузка динамической C++-библиотеки в Windows===
//hello.cpp:
#include
extern "C" void hello() {
std::cout << "hello" << '\n';
}
//main.cpp
#include
#include
===Загрузка разделяемой C++-библиотеки в Unix===
//hello.cpp:
#include
extern "C" void hello() {
std::cout << "hello" << '\n';
}
//main.cpp:
#include
#include
int main() {
using std::cout;
using std::cerr;
cout << "C++ dlopen demo\n\n";
// open the library
cout << "Opening hello.so...\n";
void* handle = dlopen("./hello.so", RTLD_LAZY);
if (!handle) {
cerr << "Cannot open library: " << dlerror() << '\n';
return 1;
}
// load the symbol
cout << "Loading symbol hello...\n";
typedef void (*hello_t)();
// reset errors
dlerror();
hello_t hello = (hello_t) dlsym(handle, "hello");
const char *dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol 'hello': " << dlsym_error <<
'\n';
dlclose(handle);
return 1;
}
// use it to do the calculation
cout << "Calling hello...\n";
hello();
// close the library
cout << "Closing library...\n";
dlclose(handle);
}
Ключи линковщика:
g++ -shared -o hello.so hello.cpp
g++ -o main main.cpp -ldl