| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Fortran > Dll из фортрана в c# |
| Автор: Jon89 27.2.2012, 19:58 |
| Здравствуйте всем)) Сразу говорю что я новичок и прошу не кидаться камнями за глупые вопросы. Проблема: Надо сделать dll в fortran. Подключить ее к c#. И из с# вызвать функцию написанную в фортране. Может кто нить на пальцах объяснить как это сделать. Был бы очень признателен за примеры кода и в Fortran и в c#)))) Заранее спасибо за ответы и потраченное на меня время) |
| Автор: FCM 9.3.2012, 08:34 |
| Какой компилятор фортрана используется? |
| Автор: Jon89 11.3.2012, 08:11 |
| Стандартный. Не знаю как называется)) |
| Автор: FCM 12.3.2012, 11:25 | ||||
| Стандартных компиляторов не бывает. Компиляторы конкретных производителей в той или иной степени соответсвуют стандарту Фортрана, а также предлагают расширения. Уж выясни как-нибудь, что за компилятор. Примерно - это выглядит так: Вот простейшая функция, возвращающая удвоенное значение целого аргумента для компилятора из линейки Visual Fortran.
Чтобы оформить ее в DLL, нужно создать соответствующий проект. При построении DLL-проекта будут, в частности, созданы файлы с расширением .lib и .dll. Как вызывать DLL в C# спроси на форуме по С#. А чтобы использовать DLL в С++ проекте (например, консольном проекте Microsoft Visual С++) следует обеспечить доступ С++ окружению .lib-файла на этапе компиляции, .dll-файла - на этапе выполнения. Что касается текста С++ программы, то это может быть что-то вроде:
(Обеспечить доступ к .lib-файлу можно вставив в С++ исходник директиву #pragma comment(lib, "путь_к_lib-файлу")) |
| Автор: Jon89 13.3.2012, 16:32 |
| Попробовал сделать на с++. Пишет ошибку: Запуск программы невозможен, т.к. на компе отсутствует MSVCRTD.dll Как посмотреть какой компилятор в Fortran у меня? Код в Fortran: INTEGER FUNCTION TWICE (X) !DEC$ ATTRIBUTES DLLEXPORT :: TWICE IMPLICIT NONE INTEGER, INTENT(IN) :: X TWICE = 2*X END FUNCTION TWICE Код в С++: #include <iostream> #pragma comment(lib, "Optim") using namespace std; extern "C" _declspec(dllimport) int TWICE(const int& x); void main() { cout<<10<<endl; cout << TWICE(1) << endl; system("pause"); } |
| Автор: FCM 14.3.2012, 10:43 | ||||
| Для начала, скажи, построил ли ты DLL по фортран-исходнику. Если да, то ругался ли (возможно в виде предупреждения) компилятор на директиву !DEC$ ATTRIBUTES DLLEXPORT А как ты вообще с ним работаешь в Visual Studio или как-то по-другому? Если в Visual Studio, то при создании любого проекта видны все возможные компиляторы, интегрируемые в Studio. Можно также попhобовать в фортран-исходник добавить вывод специфического для компилятора макроса. Например, в консольном проекте для Intel Fortran
PS. В современном С++ функций main должна иметь тип int (а не void) и возвращать целое
|
| Автор: Jon89 14.3.2012, 17:43 |
| Как я понимаю, я работаю через Developer Studio (хотя в Program files программа лежит в Microsoft Visual Studio). На исходники Fortran не ругался. все нормально откомпилил. получил .dll, .lib и еще несколько файлов на выходе. На код: PROGRAM DETECT_COMPILER WRITE(*,*) __INTEL_COMPILER END он ругается так: Compiling Fortran... C:\Program Files\Microsoft Visual Studio\MyProjects\Optim\Optim.f90 C:\Program Files\Microsoft Visual Studio\MyProjects\Optim\Optim.f90(3) : Error: Lead underscore not allowed WRITE(*,*) __INTEL_COMPILER --------------------------------^ C:\Program Files\Microsoft Visual Studio\MyProjects\Optim\Optim.f90(3) : Error: This name does not have a type, and must have an explicit type. [__INTEL_COMPILER] WRITE(*,*) __INTEL_COMPILER ----------------^ Error executing df.exe. Прикрепляю скрин из пуска. может может чем нибудь помочь в определении компилятора))) |
| Автор: Jon89 15.3.2012, 13:32 |
| 1. Оба построены в режиме Debug 2. Я пока что в ручную копирую оба файла (lib и dll) в папку с исходниками и в Debug (Потом все прикручу к проекту) 3. Да Скачал файл MSVCRTD.dll в инете, положил в System32, но похоже он для не для моей ОС (Seven) 1. При регистрации dll в винде "regsvr32 msvcrtd.dll" вылазит: Модуль "MSVCRTD.dll" загружен, но точка входа DllregisterServer не найдена. Проверьте, что "MSVCRTD.dll" является правильным файлом Dll или OCX и повторите попытку. 2. Самое приятное что даже не регистрируя dll в системе, она работает, даже в консоли программы появляется ПРАВИЛЬНОЕ решение (умножение на 2), но в процессе запуска вылазит целая гора ошибок и предупреждений. Компиляция без ошибок. Запуск программы. Скриншот 1. Нажимаю продолжить. Скриншот 2. В консоли появляется ответ. Потом нажимаю Повтор. Скриншот 3. Нажимаю продолжить. Скриншот 4. http://imageshost.ru/photo/169495/id1768558.html http://imageshost.ru/photo/170265/id1768557.html http://imageshost.ru/photo/162667/id1768556.html http://imageshost.ru/photo/164917/id1768555.html Одно радует, что она хотя бы заработала))) Почитал в инете, данная dll связана с RunTime C++. Пробовал на XP запустить, таже фигня вылазит(( |
| Автор: FCM 15.3.2012, 17:33 | ||
| По одной из приложенных картинок похоже в Compaq Fortran соглашение о вызове другое - надо бы посмотреть в свойствах проекта, если там есть такой пункт. Попробуй в прототип фортран-функции в С++ исходнике добавить спецификацию соглашения о вызове: __stdcall
Можно еще попробовать явно устанавливать соглашение о вызове в фортран-исходнике с помощью DEC-директив. PS/ Вот еще тут посмотри http://forum.sources.ru/index.php?showtopic=351171 |
| Автор: Jon89 18.3.2012, 10:12 |
| Огромное спасибо) в с++ заработало. кинул библиотеку MSVCRTD.dll прям в папку с исходниками, чтоб system32 не засорять Только осталось 2 проблемки - в x64 не робит данная библиотека. а в инете только такая версия. все перерыл уже - когда в с# пытаюсь тоже самое сделать, он ругается (строка вызова Twice(2)): Попытка чтения или записи в защищенную память. Это часто свидетельствует о том, что другая память повреждена. Исходники с#: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("Optim.dll", CallingConvention = CallingConvention.StdCall)] public static extern int TWICE(int A); public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { int b; b = TWICE(2); int c = b; } } } |
| Автор: FCM 20.3.2012, 12:39 |
| По использованию DLL в C# лучше спроси в соответствующем форуме. Если будет не лень, после того как заработает отпишись, как должна выглядеть соответствующая С# программа - пригодится кому-нибудь в будущем. |
| Автор: Jon89 21.3.2012, 12:40 |
| Рабочий код в С#: using System.Windows.Forms; using System.Runtime.InteropServices; namespace WindowsFormsApplication1 { public partial class Form1 : Form { [DllImport("Optim.dll")] public extern static int TWICE(ref int A); public Form1() {InitializeComponent();} private void button1_Click(object sender, EventArgs e) { int a = 3; textBox1.Text = TWICE(ref a).ToString(); } } } FCM, спасибо за помощь с кодом С++))) |