Calling a dll made with Fortran by C

79 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Hi again,

i hava a question really strange for me.

I have a fortran code as dllwhich is using this, i think to show the line:

2001 FORMAT(1X,76('*'),/,
1 ' chain = ',A24,/,
1 ' Mua = ',1PG10.4,' D',/,
1 ' Mub = ',1PG10.4,' D',/,
1 ' Muc = ',1PG10.4,' D',/,
1 ' COLUMN DENSITY = ',1PG10.4,' CM-2'/,
2 ' KINETIC TEMPERATURE = ',1PG10.4,' K',/,
2 ' ETL TEMPERATURE = ',1PG10.4,' K',/,
3 ' H2 VOLUME DENSITY = ',1PG10.4,' CM-3',/,
4 ' LINEWIDTH = ',1PG10.4,' KM/S',/,
5 ' HELIUM ABUNDANCE = ',1PG10.4,/,
6 ' STAR RADIUS AND TEM.= ',1PG10.4,' CM ;',4X,1PG10.4,' K',/,
8 ' SHELL RADIUS = ',1PG10.4,' CM ;',
8 ' DILUTION FACTOR = ',1PG10.4,/,
8 ' EPSILON-1 = ',0PF10.5,/,
9 ' ROTATIONAL LEVELS = ',I6,'; VIBRATIONAL LEVELS = ',
1 I2,' == ',I5,' RAD. TRANSIT.',/,
1 1X,76('*'))

I am calling it with the wrapper.dll and i was expecting to become some message in the command window but nothing becomes, i do not know and understand why.

Could help me?

Hi again,

i hava a question really strange for me.

I have a fortran code as dllwhich is using this, i think to show the line:

2001 FORMAT(1X,76('*'),/,
1 ' chain = ',A24,/,
1 ' Mua = ',1PG10.4,' D',/,
1 ' Mub = ',1PG10.4,' D',/,
1 ' Muc = ',1PG10.4,' D',/,
1 ' COLUMN DENSITY = ',1PG10.4,' CM-2'/,
2 ' KINETIC TEMPERATURE = ',1PG10.4,' K',/,
2 ' ETL TEMPERATURE = ',1PG10.4,' K',/,
3 ' H2 VOLUME DENSITY = ',1PG10.4,' CM-3',/,
4 ' LINEWIDTH = ',1PG10.4,' KM/S',/,
5 ' HELIUM ABUNDANCE = ',1PG10.4,/,
6 ' STAR RADIUS AND TEM.= ',1PG10.4,' CM ;',4X,1PG10.4,' K',/,
8 ' SHELL RADIUS = ',1PG10.4,' CM ;',
8 ' DILUTION FACTOR = ',1PG10.4,/,
8 ' EPSILON-1 = ',0PF10.5,/,
9 ' ROTATIONAL LEVELS = ',I6,'; VIBRATIONAL LEVELS = ',
1 I2,' == ',I5,' RAD. TRANSIT.',/,
1 1X,76('*'))

I am calling it with the wrapper.dll and i was expecting to become some message in the command window but nothing becomes, i do not know and understand why.

Could help me?

That's a format statement. I can't conclude anything from it. Is there a related WRITE statement?

If the C application is not a console-based one, you won't get a command window at all. In that case, you can create one using AllocConsole() function (USE DFWIN).

Jugoslav
www.xeffort.com

yes you areright,my bad, i forgot to include the wirte statement:

WRITE(IUNIT,2001)MOLEC,
1MUA,MUB,MUC,
1CODE_CAPA,TK,TETL,NH2,VEXP,...

I have already thyed changing the IUNIT for *

2001 FORMAT(1X,76('*'),/,
1 ' chain = ',A24,/,
1 ' Mua = ',1PG10.4,' D',/,
1 ' Mub = ',1PG10.4,' D',/,
1 ' Muc = ',1PG10.4,' D',/,
1 ' COLUMN DENSITY = ',1PG10.4,' CM-2'/,
2 ' KINETIC TEMPERATURE = ',1PG10.4,' K',/,
2 ' ETL TEMPERATURE = ',1PG10.4,' K',/,
3 ' H2 VOLUME DENSITY = ',1PG10.4,' CM-3',/,
4 ' LINEWIDTH = ',1PG10.4,' KM/S',/,
5 ' HELIUM ABUNDANCE = ',1PG10.4,/,
6 ' STAR RADIUS AND TEM.= ',1PG10.4,' CM ;',4X,1PG10.4,' K',/,
8 ' SHELL RADIUS = ',1PG10.4,' CM ;',
8 ' DILUTION FACTOR = ',1PG10.4,/,
8 ' EPSILON-1 = ',0PF10.5,/,
9 ' ROTATIONAL LEVELS = ',I6,'; VIBRATIONAL LEVELS = ',
1 I2,' == ',I5,' RAD. TRANSIT.',/,
1 1X,76('*'))

The problem is that for teh moment i am using the console but i dont even get any of this results on the screen and i do not understand why.
I am having the same problem whith this: .

WRITE(*,*)' **** LIST OF IMPLEMENTED COMMANDS ****'
WRITE(*,*)
DO L=1,NUMERO_COMANDOS,10
L1=L
L2=L1+9
IF(L2.GT.NUMERO_COMANDOS)L2=NUMERO_COMANDOS
c WRITE(*,'(10(3X,A4))')(COMANDOS(K),K=L1,L2)
WRITE(*,*)(COMANDOS(K),K=L1,L2)
ENDDO
WRITE(*,*)
WRITE(*,*)' **** HELP COMMAND NAME ****'

Could you explain me the suggestion? ive never heard about that.

about the last subject, the messages are shown on the screen using the console but without the format, i do not understand why???

Apart from that, could you explain me the idea of AllocateConsole() in the wrapper??

AllocConsole creates a console if there isn't one (e.g. in a GUI application). Normally, it's not desired in a GUI application, but may be useful while debugging. (Do you use the debugger, btw)?

I don't know why it doesn't use the format statement. As a suggestion, I'd propose that you break it into several WRITEs and several FORMATs (or, better still, embed the format in WRITE statement instead of keeping it on separate line). As it is now, it's a nightmare to parse and maintain. Maybe you'd find the answer on the way.

Jugoslav
www.xeffort.com

the purpose is not use the console as a degugger or something like that, but it is a requirement for the project, something strange is true, but the main goal is to be able to show in a panel (useas console or jst simulating it) of an interface the write commands in fortran.That is the reason I am trying to create it.
Now im checking the doc about AllocConsole, but i am worried about the fact that the formated text is not showed.

First of all, i do not know if it is the rigth place to describe this problem, but if it is not, moderator please tell, and i quit this message.
Ok the problem with the project right know is to show in a GUI the messages that the Fortran library is sending. Those are shown when the Java code is execute in the console, but not using a GUI i.ve implemented besides the new definition of the system.out:
System.setOut(new PrintStream(new OutputStream() {
public void write(int b) throws
IOException {
// write to the text area
textArea.append(String.valueOf((char)b));
// write to the default System.out
sysOut.write(b);
}
}));

now what a was thinking about is if there isany function in fortran to specify where to write, beacuse for the moment im using write(*,*), but iam not sure how it will affect the output :?
Thanks

Well, write(*) writes into the "standard output". Standard output is by default a console, but it can be redirected to a file or pipe by the calling process or code (SetStdHandle API). However, as far as I know, Fortran run-time-library grabs the standard output handle first time it encounters an I/O statement (or, perhaps, specifically, a write(*) statement) and subsequent SetStdHandle's will not affect where write(*) writes (Note: that was my casual observation, take it with a grain of salt).

So, if there is no console, standard output is by default "nowhere" (aka dev/null in unixspeak). Now, an early call to AllocConsole might solve the problem, as AllocConsole is supposed to also redirect standard output to itself. A call to GetFileType(GetStdHandle(STD_OUTPUT_HANDLE)) should tell you where the standard output is going to.

I don't know Java to be able to tell what the code fragment you posted is supposed to do.

Perhaps the best solution would be to pass a Fortran-callable routine in C or Java to the dll, and the Fortran code should call it with an appropriate text argument. However, it looks difficult because of 3 languages involved.

Jugoslav
www.xeffort.com

I agree that it will be hard, moreover because of i do not know how the write or system.out operates with the OS. Due to the lack of time of the project and the fact the beneficts of this implementation wont be so big, i gonna try to put this write messages into a file(eg write(*,*)"New chain:") or pipe and make java read them. So i have not idea how can i do that a statement will be stored in a file, and if it is possible to save it into a file and at the same time show it on the console.
Could u give me a hand? Thanks

I recently posted a sample with pipe-talking between two processes (I think nothing prevents you to do this within the same process, providing that you don't redirect "primary" stdin/stdout as in the sample), where "child process" stdin/stdout are redirected to a pipe (so that it uses only READ(*) and WRITE(*)) (Communication between exe files thread).

But no, you can't have double output simultaneously with one WRITE statement; at least, you have to duplicate WRITE statements.

What does GetStdHandle(STD_OUTPUT_HANDLE) return when called from Fortran code in GUI app? What does GetFileType() return for it? Have you tried AllocConsole()?

Message Edited by JugoslavDujic on 02-20-2006 04:40 PM

Jugoslav
www.xeffort.com

I prefer to use message boxes for displaying status in GUI apps, rather than fiddling with consoles. I'll admit that this isn't an ideal solution for everyone.

Steve - Intel Developer Support

If it just status you want, then I agree with Steve about message boxes. Here is a trimmed-down example of your formatted message as it would appear and here is the code

  character(256) message
  character*24 chain, crlf*2
  real*8 mua,mub,muc,colden

   chain='abcdefghijklmnopqrstuvwx'
   mua=1.0d+00
   mub=2*mua
   muc=3*mua
   colden=1.0d-10
   crlf=char(10)//char(13)
  write(message,2001)crlf,chain,crlf,mua,crlf,mub,crlf,muc,crlf,colden,crlf

  2001    FORMAT(1X,24('*'),a2, &
      '  chain   = ',A24,a2, &
      '  Mua                 = ',1PG10.4,' D',a2, &
      '  Mub                 = ',1PG10.4,' D',a2, &
      '  Muc                 = ',1PG10.4,' D',a2, &
      '  COLUMN DENSITY      = ',1PG10.4,' CM-2',a2, &
       1X,24('*'))

  	ret=MESSAGEBOX(ghWndMain, message//''c,&
                    'Test of Output'C, &
					  MB_ICONEXCLAMATION .OR. MB_OK)
  

You need a:

use ifwin

in there to make the MessageBox and MB_xxx symbols available.

Steve - Intel Developer Support

the idea of the message box is really good, but it moves away from the specs. It has to be an interface with an area where what the library does will be shown. So all the operations the library does use the command write. My first idea was the simple but the hardest, to redirect the outpu of the console in the java, but i did not pay attention that only the java messages would be shown and not the fortran ones, which are the ones i am interested in. I have been reading about AllocConsole comments and i am afraid of getting the same results, just the printf of C would be redirected (this is a supposal, i havent yet check it)
So the final option i think is better is to use a pipe, but i cant avoid feeling or thinking is not the best solution.

Whoww i have read a little bit of the Pipes.f90 and it si really hard.
Question how can i change themodule dfwin? because in the Fortran PowerStatio 4.0 is not found, Either the ifwin.
Jugoslav could u explainit a littel bit , i mean, which are the basic steps to create a Pipe just where the fortran write, it has not to read.
Thanks

by the way an easy question

how can i write the messages into a file?, i mean ive never had worked with files so i hav no clue how to create, open,write and close them

Look up OPEN statement for write to file -- that's the simplest way to go. There is plenty of such code on this forum and elsewhere.

My Lord, you're still using Microsoft Fortran PowerStation 4.0 ?! It's not a problem if it suits you well, but note that it's 10 years old (and one of buggiest compilers I've seen).

The pipes sample might work if you USE MSFWIN instead, but I can't offer any guarantees on FPS4.0. It had a rather incomplete set of API translation, and I can't tell whether the call prototypes are compatible with IVF ones. Basically, you only need to redirect stdin to "read" end of the pipe (read from C/Java) and stdout to "write" end (fortran WRITE). However, it's still questionable whether it will work. If you can't get simple WRITE to write to the console, it's unlikely to work for a pipe &ndash' the issue is when Fortran run-time library "associates" the STD_OUTPUT_HANDLE with WRITE(*) stream, and whether it looks up to it later. If the association happens at dll load time, you can't prevent it (except perhaps by redirecting first from C and then calling LoadLibrary/GetProcAddress).

Jugoslav
www.xeffort.com

hi

i am trying to use some of the code you did in the pipe to test how it works, but i am getting some troubles:

!code form Jugoslav

INTEGERiStdoutWr, iStdoutRd,iret
TYPE(T_PROCESS_INFORMATION):: PI1
TYPE(T_STARTUPINFO):: SI1
TYPE(T_SECURITY_ATTRIBUTES):: SA1

SA1.nLength = sizeof(SA)
SA1.bInheritHandle = TRUE
SA1.lpSecurityDescriptor = NULL
iret = CreatePipe(LOC(iStdoutRd), LOC(iStdoutWr), SA, 0)
iret = SetHandleInformation( iStdoutRd, HANDLE_FLAG_INHERIT, 0)

SI1.cb = sizeof(SI1);
SI1.hStdError = iStdoutWr
SI1.hStdOutput = iStdoutWr
SI1.dwFlags = STARTF_USESTDHANDLES

PI1 = T_PROCESS_INFORMATION(0, 0, 0, 0)

iret = SetStdHandle(STD_OUTPUT_HANDLE, iStdInWr)

WRITE(*,*) 'Prueba'
iret = CloseHandle(iStdoutWr)
iret = CloseHandle(iStdoutRd)

iret = CloseHandle(PI1.hProcess)
iret = CloseHandle(PI1.hThread)

i am becoming some errors:

1. i have changed the names adding 1 because it sayd multiple type declarations for symbol PI
2. with this lines i am getting this two errors:

error FOR2290: implicit type for ISTDINWR
error FOR2290: implicit type for SIZEOF

3. where is it written? i mean in order to tell java where to read??

Thanks for your help

In principle, it's sufficient to do that somewhere on Java or C wrapper code. For instance:

//C wrapper
#include "windows.h"
...
HANDLE hReadEnd, hWriteEnd;
CreatePipe(&hReadEnd, &hWriteEnd, NULL, 0);
SetStdHandle(hWriteEnd, STD_OUTPUT_HANDLE);
SetStdHandle(hReadEnd, STD_INPUT_HANDLE);

However, forget about the idea if you're using single-threaded exe, even if you succeed in redirecting I/O to the pipe, you cannot simultaneously WRITE on Fortran side and ReadPipe on C side. Pipes example uses two processes which run concurrently, so one can wait for the other to complete I/O operation and display the output as soon as it's done. In your case, you could only display the pipe contents after Fortran has finished.

Jugoslav
www.xeffort.com

man i owe you a couple drinks, thanks for the help,

but please tell me that there is a way in java using this editor, to write a file besides open an unit and write on it, because it makes me change a lot of lines that are done as write(*,*) and i really hate this kind of work

Thanks

Well, you can always open all .for files in a decent text editor and just replace all occurences of "WRITE(*" with "WRITE(42". Even if the editor doesn't have "replace across files" capability, I guess it's not that much of a job unless you have 100 source files or so?

Jugoslav
www.xeffort.com

Hi,

i was performing some tests to learn how to use AllocConsole, but the repplies werent so good as I expected. The wrapper is creating a console in order to show the printf and write messages (from the Fortran and of course the own library). I am creating it as follows:

JNIEXPORT void JNICALL Java_Main_console(JNIEnv *env, jobject jobj)

{

static const WORD MAX_CONSOLE_LINES = 500;

int hConHandle;

long lStdHandle;

CONSOLE_SCREEN_BUFFER_INFO coninfo;

FILE *fp;

// allocate a console for this app

AllocConsole();

// set the screen buffer

GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);

coninfo.dwSize.Y = MAX_CONSOLE_LINES;

SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);

// redirect unbuffered STDOUT to the console

lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE);

hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "w" );

*stdout = *fp;

setvbuf( stdout, NULL, _IONBF, 0 );

// redirect unbuffered STDIN to the console

lStdHandle = (long)GetStdHandle(STD_INPUT_HANDLE);

hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "r" );

*stdin = *fp;

setvbuf( stdin, NULL, _IONBF, 0 );

// redirect unbuffered STDERR to the console

lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE);

hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);

fp = _fdopen( hConHandle, "w" );

*stderr = *fp;

setvbuf( stderr, NULL, _IONBF, 0 );

// point to console as well

ios::sync_with_stdio();

printf("I did it!
");

cout << "Hello"

}

Please any idea why is not any message shows?

thanks

Which message? Your code works for me, as well as the Compaq Visual Fortran dll called from C GUI app. I can't predict what PowerStation will do though. Here's the attachment, with binaries in Release folder.

Jugoslav
www.xeffort.com

The messages are the printf. When i am calling the dll with the java, it opens a console whichshows nothig, and i mean, the printf just below the creation of it.
I hope anddo not thinkthat Compaq Visual Fortran and the compiler i have to use will send the messages in differents places.
ive tryed your example and i observed that instead of using the native, you usean api. Wiht the gui i should call this function :?

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPSTR lpCmdLine,

int nCmdShow)

{

//create the console

startConsoleWin();

}

JNIEXPORT void JNICALL Java_Main_console(JNIEnv *env, jobject jobj)

{

//call the api????

printf("1
");

}

Message Edited by patuco on 02-22-2006 03:10 AM

I don't have Java, know Java, nor know how its p-code works and interacts with the system APIs. I was merely trying to demonstrate that it works in a native GUI app I don't have an idea how Java environment affects the behavior.

Sorry for having to make such disclaimers, but I really can't offer much help regarding Java setup, and tell why the concrete code doesn't work. There are too many low-level issues involved. You can also try some Java-related group comp.os.ms-windows.programmer.win32 on groups.google.com.

Jugoslav
www.xeffort.com

do not worried about the disclaimers, it is normal and happens a lot.

Just a question to know your opinion after reading again what you said about pipes in some posts before.

Will be possible to use pipes to write the outputs of the librariy to a file? (I am asking it because i know how to use pipes in java, and this option wont make me change the fortran files, which as i supposed you suspect are not implemented for me, besides the fact i should review and correct them).

Thanks

Pages

Leave a Comment

Please sign in to add a comment. Not a member? Join today