Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [Interop] Вызов из C++ процедур в DLL, Вопросы вызова, примеры и обсуждение 
V
    Опции темы
Cr@$h
Дата 11.7.2006, 03:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Исследователь
***


Профиль
Группа: Участник Клуба
Сообщений: 1693
Регистрация: 3.4.2005
Где: Санкт-Петербург, Россия

Репутация: 1
Всего: 41



В данной теме опишу в нескольких словах, как вызывать из C++ процедуры в DLL, написанной на Fortran. Здесь использую также материалы одного пособия, поэтому, к сожалению, написанное в посте нельзя будет плагиатить, размещая на той же Forki (Fortran Wiki) или используя в традиционном смысле. Быть может, я сделаю это позже, если Forki станет востребованной и будет время.

Терминология

Обратим внимание на используемую терминологию.

Процедурами (procedures) будем называть функции (functions), возвращающие значение, и подпрограммы (subroutines), не возвращающие значения. Тем не менее, в некоторых языках программирования только подпрограммы называют процедурами, например, в Pascal — Procedure (которые не возвращает никакого значения). Почти во всех остальных языках процедуры используются в правильном значении, например, Procedure в Ассемблере и Function и Subroutine в Fortran.

Когда говорится: «Вызов процедуры из основной программы», это значит, что в основной программе осуществляется вызов процедуры, а не, как это может показаться, вызов процедуры, которая находится в основной программе. Например: «Вызов из С++ процедуры в DLL», означает, что на языке С++ осуществляется обращение к процедуре, находящейся в динамически подключаемой библиотеке (DLL). «Вызов неуправляемого кода в DLL» означает, что осуществляется вызов неуправляемого кода, находящегося в DLL, а не то, что вызов неуправляемого кода происходит в самой DLL. Исключения могут быть для причастий: «Процедура, вызываемая из C#» (called from C#), часто означает, что производится вызов процедуры, написанной на C#, а не сам вызов какой-то процедуры в программе C#. Но и здесь не придется ломать голову — истинный смысл будет сразу понятен из контекста. Таким образом, в русско- и англоязычной терминологии вызовов предлог в (in) означает, где находится вызываемый код, а предлог из (from) указывает, что его вызывает. Это кажется до-вольно простым, но, не зная этих тонкостей, можно воспринимать текст в неправильном и даже противоположном смысле. Например, обращаясь к части заголовка темы, согласно этой терминологии выражение: "Вызов из C++ процедур в DLL", означает, что в программе C++ проводится вызов процедур, находящихся в DLL, а не вызов в самой DLL процедур из С++, что ведь тоже возможо!

Применяемая терминология является общепринятой и устоявшейся в программистском сообществе и позволит правильно понимать руководства, описания и другие документы.

Область использования могоязыкового программирования и соглашение о вызовах

Многоязыковым программированием (mixed-language programming) называют процесс разработки программ, в котором исходный код написан на двух или более языках программирования. Оно позволяет вам:
  • вызывать уже существующий код, который написан на другом языке;
  • использовать процедуры, которые может оказаться сложно реализовать на определенном языке;
  • получать доступ к специфическим средствам и возможностям языков и сред разработки ПО;
  • получать преимущества в скорости работы.
При многоязыковом программировании можно применять различные языки. Например, это могут быть MASM, C, C++, Basic, Pascal, Delphi, C#, Fortran и др. Многоязыковое программирование в 32- и 64-разрядных системах отличается от программирования в 16-разрядных системах и во многих отношениях легче.

Проекты большинства сред разработки, таких как Microsoft Visual Studio .NET и Borland Developer Studio, поддерживают один язык, поэтому код на каждом определенном языке должен быть в своем собственном проекте. При этом сами решения (solutions) могут содержать проекты, написанные на разных языках программирования.

Для успешной разработки многоязыковых программ должны быть приняты правила для присваивания имен переменным и процедурам, для использования стека и для передачи параметров между процедурами, написанными на разных языках. Все вместе эти правила называются соглашением о вызовах, или соглашением о связях (calling convention).

Соглашение о вызовах включает в себя:
  • Организация стека (stack considerations)
    • Функция получает фиксированное или переменное число параметров?
    • Какая из программ очищает стек после вызова: вызывающая или вызываемая?
    • В каком порядке заносятся переменные в стек?
  • Соглашения по присваиванию имен (naming conventions)
    • Значим ли верхний или нижний регистр?
    • Изменяются ли при компиляции внешние имена с помощью различных префиксов?
  • Протокол передачи параметров (argument passing protocol)
    • Параметры передаются по значению или по ссылке?
    • Какие типы данных и типы структур эквивалентны среди языков?

Вызов из C++ процедур в DLL, написанных на Fortran
Для удовлетворения и указания используемых соглашений о вызовах должны использоваться специальные директивы компиляторов, как при создании процедур библиотеки, так и при их вызове из неё.
Откапал уже приводимый мною на форуме пример.
Пусть у нас есть процедура в Dll, написанная на Fortran:
Код

function FMin( ax, bx, F, tol )
    !DEC$ ATTRIBUTES DLLEXPORT, STDCALL, DECORATE, ALIAS : "FMin" :: FMin

    Interface
        function F( x )
            !DEC$ ATTRIBUTES STDCALL :: F
        
            real F
            real, intent(in) :: x
        end function F
    end interface
        
    real FMin
    real, intent(in) :: ax, bx, tol

    ...
end function FMin

Здесь я использовал директивы: STDCALL -- для выполнения стандратных соглашений о вызовах, DECORATE -- компилятор автоматически думает, ставить ли перед именем процедуры _, ALIAS -- задает имя процедуры, под которым оно будет храниться в Dll, с учетом уже регистра. Callback-функция F(x) описывается в интерфейсе.
Вот как обращаться к такой функции из C++:
Код

#include "stdafx.h"

extern "C" __declspec(dllimport) float __stdcall FMin( float ax, float bx, float (__stdcall *F)( float x ), float tol );

float __stdcall F( float x ) {
    return( float(x*( x*x - 2. ) - 5.) );
}

int _tmain( int argc, _TCHAR *argv[] ) {
    float a, b, z, tol;
    
    a = 0.;
    b = 1.;
    tol = 1.e-5f;
    z = FMin( a, b, &F, tol );
    printf( "z = %f", z );

    getchar();
    return 0;
}

В extern объявляю прототип вызываемой Dll-функции. Обрати внимание, как там описана функция-параметр. Затем идет пример функции-параметра и пример вызова. И везде указания на стандартное соглашение о вызовах
PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Fortran | Следующая тема »


 




[ Время генерации скрипта: 0.0946 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.