======Динамическая загрузка библиотек====== На данной странице описаны некоторые технологии (приемы программирования), которые используются в текущем проекте. Под динамической загрузкой разделяемой библиотеки понимается загрузка исполняемого кода, находящегося в библиотеке, во время выполнения программы. Данный подход позволяет компилировать функции на языке //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