Calling a dll made with Fortran by C

Calling a dll made with Fortran by C

Hi,
i am getting crazy tying to find out where or why is teh problem in the program I'm doing. If someone could help me, it would be great.
Ill explain you my problem:
i am doing some test to try out how the jni of javaworks. i implemented a dumy program which only purpose is to call a Frotran dll which has to show on the screen the typical Hello world. I did the C++ wrapper using the visual studio .net. Ive already accomplished the communication between the wrapper and Java. in a second stage I try to do the same but with the wrapper calling the fortran dll, and here is where the problems occur: the function called by the wrapper located in the fortran dll is not "found":
ReadValue error LNK2019: smbolo externo _PRINTER@0 sin resolver al que se hace referencia en la funcin "long __stdcall Java_ReadValue_getValue(struct JNIEnv_ *,class _jobject *)" (?Java_ReadValue_getValue@@YGJPAUJNIEnv_@@PAV_jobject@@@Z)
The Fortran code is as follows:INTEGER FUNCTION PRINTER()
!decs attributes c :: PRINTER
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'PRINTER'::PRINTER
WRITE(6,'("-- FORTRAN funcion printer --")')
PRINTER=2
END

as you can observed is quite obvious.
So as the wrapper:

#include "stdafx.h"

#include "stdio.h"

#include "ReadValue.h"

#include "jni.h"

extern "C" __stdcall int PRINTER();

// i even try with : extern "C" __cdecl int PRINTER();

JNIEXPORT jint JNICALL Java_ReadValue_getValue(JNIEnv * env, jobject jobj)

{

printf("-- A ver si funciona la referencia --
");

int result = PRINTER();

printf(" -- valor de retorno ke leyo del archivo -- ",result);

return result;

}

Anyone can help me?? Thanks.

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

!DEC$ATTRIBUTES syntax is a bit difficult to get right -- and you got it wrong :-). Here we go:

  • all symbols have prepended an underscore (unless overriden with ALIAS, see below)
  • stdcall symbols (CVF default) have @n appended. cdecl symbols (IVF default) don't.
  • both !DEC$ATTRIBUTES STDCALL and !DEC$ATTRIBUTES C imply lowercase symbols (unless overriden with ALIAS, see below) and call by value.
  • ALIAS: specifies the exact exported symbol name, unless combined with DECORATE
  • ALIAS, DECORATE in combination specifies that the case (upper/lower) is to be used from alias, but decoration (_ ... @n) appended.
  • You always need extern "C" when calling from C++.

So, any of the following (and more) combinations will work:

extern "C" __cdecl int printer()
!DEC$ATTRIBUTES DLLEXPORT, C:: PRINTER
--
extern "C" __cdecl int PRINTER()
!DEC$ATTRIBUTES DLLEXPORT, C, DECORATE, ALIAS: "PRINTER":: PRINTER
--
extern "C" __stdcall int Printer()
!DEC$ATTRIBUTES DLLEXPORT, STDCALL, DECORATE, ALIAS: "Printer":: PRINTER
--
extern "C" __stdcall int Printer()
!DEC$ATTRIBUTES DLLEXPORT, STDCALL, ALIAS: "_Printer@0":: PRINTER
--

HTH
Jugoslav

Jugoslav
www.xeffort.com

Thanks a lot Jugoslav,
ive tryed your suggestions but no one works.
The fact is thatI need the fortran function to be exported in orther to be called. The problem im facing with is that the !DEC$ATTRIBUTES command does not export it, or at least is unabel to see by using the dependancy walker. Apart from that, the .net is still complaining about the linkage. I am not an expert using it, so i do not know if the problem could be related with the association of the .lib into the project.
The source code i'm working right now is as follows:

INTEGER FUNCTION PRINTER()
!MS$ATTRIBUTES DLLEXPORT,STDCALL,ALIAS:'_printer@n'::PRINTER
WRITE(6,'("-- FORTRAN funcion printer --")')
PRINTER=2
END

and the wrapper:

extern "C" __stdcall int _printer();

JNIEXPORT jint JNICALL Java_ReadValue_getValue(JNIEnv * env, jobject jobj)

{

printf("-- A ver si funciona la referencia --
");

int result = _printer();

printf(" -- valor de retorno ke leyo del archivo -- ",result);

return result;

}

Any idea?

I didn't mean (@n) literally -- n is 4* the number of arguments, in this case zero (0). I suggest using DECORATE attribute, as it will take care about such details. Also, you don't need the leading underscore in C declaration -- the underscore is assumed by both Fortran and C compilers and now you're declaring "__printer@0" instead of "_printer@0"

I don't see how it's possible that it doesn't get exported. If nothing is exported, you wouldn't get the .lib file produced at all.

Jugoslav

Jugoslav
www.xeffort.com

ok, thanks for thetip, but as i commented you, no function is being exported (take a look in the attachedment). Coulb it berelated with the !DEC and the !ms

INTEGER FUNCTION PRINTER()
!DEC$ATTRIBUTES DLLEXPORT, STDCALL, DECORATE, ALIAS: "Printer":: PRINTER
WRITE(6,'("-- FORTRAN funcion printer --")')
PRINTER=2
END

I have no clue. As I said, you wouldn't get a .lib if you don't have any exports.

I noticed that Dependency Walker shows that you're looking at fROtran.dll is it misspelled all the way or you're just loking at a wrong dll?

Jugoslav

Jugoslav
www.xeffort.com

hi, i was performing some tests with the fortran code.

this is the version, the library is built from:

INTEGER FUNCTION Printer()
!MS$ATTRIBUTES DLLEXPORT, C, ALIAS: '_Printer':: Printer
WRITE(6,'("-- FORTRAN funcion printer --")')
PRINTER=2
END

the question is the wrapper call because it is keeping giving me back the linkage error??????

extern "C" _stdcall int _Printer();

JNIEXPORT jint JNICALL Java_ReadValue_getValue(JNIEnv * env, jobject jobj)

{

printf("-- A ver si funciona la referencia --
");

int result = _Printer();

printf(" -- valor de retorno ke leyo del archivo -- ",result);

return result;

}

the .lib is added on the project (to avoid this reply):

Project->Properties->Link->Input

aditional dependencies: fortran.lib

Any idea?

yes it is a misspell :) i'm maintaining it because i is not so important in this stage. don't you agree?.

Please go back and read my first post. Don't just randomly insert attributes and underscores. This time you have C versus STDCALL and the extra underscore in C version. Try this:


!MS$ATTRIBUTES DLLEXPORT, C, DECORATE, ALIAS: 'Printer':: Printer
extern "C" __cdecl int Printer();

Jugoslav

Jugoslav
www.xeffort.com

As for the misspell, I don't mind as long as it's consistent. However, you mentioned "fORtran.lib" but you appear to be using "fROtran.dll" -- which one is right?

Are you sure you have the f**tran.lib in the same directory as f**tran.dll, with the same timestamp?

Jugoslav

Jugoslav
www.xeffort.com

ok let's reorganized everything.

the names i am using are frotan.dll and frotan.lib when i created the fortran library i didnt pay attention on it.

the reason im using the command !MS$ATTRIBUTES is, as i comment you before, because is the only way the dependancy is showing me the exported functions and subroutines.

With the option DECORATE i have the problem my compiler does not recognize it (i have to use the Microsoft Developer Studio).So the command i am using is:

!MS$ATTRIBUTES DLLEXPORT, C, ALIAS: "Printer":: PRINTER

After taking a look in the dependancy walker, i can read the function Printer (as we expected). All files, included .lib and .dll, are in ALL thedirectories created by the .net for the wrapper

now im trying to call this funct from the wrapper

extern "C" _cdecl int Printer();

and in the function:

JNIEXPORT jint JNICALL Java_ReadValue_getValue(JNIEnv * env, jobject jobj)

{

printf("-- CALLING THE NATIVE --
");

int result = Printer();

But im continuing becoming the same link error.

So i think the properties of the project are wrong configured. I know i have to add the .lib to teh project havent I?But maye im doing it wrong. Could you hep me, please?

Before that i made some test in linux and they work correctly but one of the restrictions is the program should be executed in windows andthe way of working withthe wrapper is a bit different. Instead of using two different libraries, only one is used. But as i told you, the requirements are different.

Message Edited by patuco on 02-07-2006 01:19 AM

You're using CVF6.1 or even older, right? That's >6 years old.

Since DECORATE is not available, the only decoration for C function is the underscore, so the attributes line should be:

!MS$ATTRIBUTES DLLEXPORT, C, ALIAS: "_Printer":: PRINTER

If you have the .lib, and the function is correctly exported, the only issue you have is mismatch in symbol naming. With the above line substituted, it should (finally) work.

Jugoslav
www.xeffort.com

Thanks a lot Jugoslav,

finally it works. The problem was in the underscores in the wrapper.

Thanks a lot for helping me and thetimeyou've spend with this.

The code used was:

!MS$ATTRIBUTES DLLEXPORT, C, ALIAS: "_Printer":: PRINTER

extern "C" _cdecl int Printer();

By the way, last comment, as i read in your first post about the parameters, if i have to call a function/subroutine with parameters the command in Fortran should look like this ?

!MS$ATTRIBUTES DLLEXPORT, C, ALIAS: _Printer@n:: PRINTER

and as you said yesterday, being the n the number of parameters.

Take care

cdecl (!DEC$ATTRIBUTES C) routines never have @n appended -- only stdcall ones. With the latter, n is generally equal to 4*number of arguments (but it can get complicated with string arguments or if larger structures are passed by value). You can take a look at e.g. DFWIN.f90 or Kernel32.f90 (I'm not sure when the former was split into smaller ones) from compiler's Include folder to see how it's done for Windows API routines (which are stdcall).

Jugoslav
www.xeffort.com

Hi there,

I add another question that is related with the last one in the fact of using the dll, but not in the same way.

The point is that the fortran code is getting and changing some values of common variables of it, that the front- end need to show the results. In order to accomplish it, some functions, like getvalue or setvalue have been implemented in fortran, being the return value as follows:

INTEGER FUNCTION GETVALUE()
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getvalue'::GETVALUE
INCLUDE 'common.lvg'
GETVALUE=NUM_MAX
END FUNCTION

The wapper does the assignment as follows:

int result = Getvalue();

printf(" -- Fin C llama a fortran para get -- %i --
",result);

I think im not considering some fact of fortranor communication between dlls. Am I?

And the question is...?

There are several ways to pass the data, the simplest being argument passing, like:

SUBROUTINE GetValues(iVal1, rVal2, aVal3)
integer, intent(out):: iVal1
real, intent(out):: rVal2
real, intent(out):: aVal3(*)
!DEC$ATTRIBUTES C, REFERENCE, ALIAS: "_GetValues":: GetValues
INCLUDE "common.lvg"
iVal1 = NUM_MAX
rVal2 = Foo
DO i = 1,nn
aVal3(i) = Bar(i)
END DO
END SUBROUTINE

extern "C" void GetValues(int*, float*, float*)
...
float rResult3[...]
GetValues(&iResult1, &rResult2, rResult3)
Jugoslav
www.xeffort.com

it is just a question about declaring the extern functions in the wrapper:

anyone knows whichare the differences between:

extern "c" int Printer();

extern "c" __declspec(dllexport) int Printer();

?????

ive read about the parameter __declspec but i do not understand it as i would like.

Thanks,

Take care

__declspec(dllexport/dllimport) is the same as !DEC$ATTRIBUTES DLLEXPORT/DLLIMPORT - for exporting and importing symbols in dll.

__declspec(dllimport) can be omitted; a function can be imported without that attribute.

Jugoslav
www.xeffort.com

Hi,

i have a problem with the conversion of a char* to string i do not get where the mistake is in the code of the native function:

JNIEXPORT jstring JNICALL Java_Main_get_1name(JNIEnv *env, jobject jobj, jint param)

{

char buf = (char*)malloc(max_char);

//Call the function in fortran

strcpy(buf, Getname(param +1));

return (*env)->NewStringUTF(env, buf);

}

anyone knows why?

Message Edited by patuco on 02-07-2006 01:20 AM

I don't speak Spanish, but it seems that the C++ compiler doesn't know what "JNIEnv" is -- maybe it's misspelled (wrong case?), or you have to #include appropriate header file.

Jugoslav
www.xeffort.com

it was a problem related with pointers, i mean ,instead of using (*env), i tested with env-> and it worked

Message Edited by patuco on 02-07-2006 01:21 AM

Hi,

i have a problem, i should be doing something terrible because i.m getting an exception from the java virtual machine. Im trying the dll to return to the java a String so im doing like follows:

wrapper:

JNIEXPORT jstring JNICALL Java_Main_get_1name(JNIEnv *env, jobject jobj, jint param)

{

char buf[80];// = (char*)malloc(num_chars);

strcpy(buf, Getname(param +1));

return js;

and the fortran:

CHARACTER(80) FUNCTION GETNAME(VALUE)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
INCLUDE 'COMMON.LVG'
INTEGER VALUE
WRITE(*,*) "The VALUE is ", MOL(VALUE)
GETNAME=MOL(VALUE)
END FUNCTION

and the error comes where the fortran call is located. :?

# An unexpected error has been detected by HotSpot Virtual Machine:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x02cb4c7c, pid=2804, tid=1748
#
# Java VM: Java HotSpot Client VM (1.5.0_06-b05 mixed mode, sharing)
# Problematic frame:
# C [mlvg.dll+0x14c7c]
#
# An error report file with more information is saved as hs_err_pid2804.log
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#

Anyone could give me a clue? Thanks.

Message Edited by patuco on 02-07-2006 01:17 AM

I am absolutely certain that what Java wants to see for a function returning a string isn't what Fortran provides.

In Intel Fortran, a function that returns a CHARACTER value has the return variable passed as a hidden first argument, as if it were a subroutine with an extra character argument. That also affects where the string lengths are.

Also, do you know for certain that Java wants to call routines using the C calling mechanism and not STDCALL?

Steve - Intel Developer Support

hi,
i'm sure i need the c cuz the test i did showing on the screen the value worked. It is something related with the returning value, i will try what Jugoslav suggested days befor, passing the array as parameter, but my goal was trying to avoid it.

and of course what java expect is not what fortran provides... but that is one of the purpose of the wrapper: it receives a char * from Fortran and it will transform it into an String for Java.

The point is that ive never used the type CHAR(80), is something i found looking through the help, so i do not know how can i implement a function in fortan which returns a variable which contains only characters.

subroutine GetName(name)
!DEC$ATTRIBUTES whatever
CHARACTER(*) name
name = ...
name = trim(name)//char(0)
end subroutine GetName

extern "C" Getname(char*, int)
...
Getname(buf, 80)

Jugoslav
www.xeffort.com

Hi everyone,

Ive been trying to copy the string in the fortran code (it is equivalent as C123TE) in the wrapper but I could accomplish it.

The wrapper calls the native as follows:

Declaration

extern "C" __declspec(dllexport) char* Getname(char *,int );//_Getname

Implementation

JNIEXPORT jstring JNICALL Java_Main_get_1name(JNIEnv *env, jobject jobj, jint param)

{

char *buf = (char*)malloc(80);

buf = " ";

printf("Before calling the wrapper: %s
",buf);

//char buf[80];

printf("
--C Calling the native
");

Getname(buf, param);

printf("%s
",buf);

printf("-- C Return form the native->buf:
", buf);

return env->NewStringUTF(buf);

}

The fortran is as follows (names of the variables are unsignificant):

Mol is an array of chars which combines signs and numbers with values like: CE23R, O89R, R4576,23R45.

SUBROUTINE GETNAME(ARRAKY, VALUE)

!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME INCLUDE ''COMMON.LVG'

INTEGER VALUE

CHARACTER*(*) ARRAKY

WRITE(*,*) "The INPUT is ", ARRAKY

WRITE(*,*) "The FORTRAN is ", MOL (VALUE)

ARRAKY= MOL (VALUE)

ARRAKY = TRIM(ARRAKY)

WRITE(*,*) "The ARRAKI is ", ARRAKY

END SUBROUTINE GETNAME

Output:

Before calling the wrapper:

--C -- Calling the native

The INPUT is h

The FORTRAN is C17B

The ARRAKI is C

-- C Return form the native:

As you can observed only the first character is copied. :?

I`ve tried using an auxiliar char* and using a line like :

AYU(1:10)=MOL(VALUE)(1:10)

being the string copied into AYU ok but not in one passed as parameter:

ARRAKY(1:10)=AYU(1:10)

so as in the wrapper defining a static array (buffer[80]) but getting the same results.

Do you have any idea or suggestion? Thanks.

Message Edited by patuco on 02-07-2006 01:15 AM

Message Edited by patuco on 02-07-2006 01:18 AM

When a string argument appears in Fortran code, it is "transcribed" as two arguments in C. One is char* (argument address) and the other is int (buffer length). By default, the latter is passed at the end of argument-list.

So, for the given Fortran routine, the C prototype should be:

extern "C" __declspec(dllexport) 
char* Getname(char* string, int value, int stringlen);

Stringlen should be 80 in this case, obviously. Also, you should append a char(0) to the Fortran string, so that it can be parsed correctly in C:

ARRAKY= TRIM(MOL(VALUE))//CHAR(0)

Jugoslav
www.xeffort.com

hi,

ive tryed your suggestions but i do not get what i am not considering,because the same behaviour is produce, i mean, the fortran code is parse:

SUBROUTINE GETNAME(ARRAKY, VALUE)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
c!MS$ATTRIBUTES REFERENCE :: ARRAKY
INCLUDE 'COMMON.LVG'
INTEGER VALUE
CHARACTER*(*) ARRAKY
WRITE(*,*) "The INPUT is ", ARRAKY
WRITE(*,*) "The FORTRAN is ", MOL(VALUE)
ARRAKY= TRIM(MOL(VALUE))//CHAR(0)
WRITE(*,*) "The ARRAKI is ", ARRAKY
END SUBROUTINE GETNAME

being call in the way:

extern "C" __declspec(dllexport) char* Getname(char * ,int ,int );

//string, str_length, element

JNIEXPORT jstring JNICALL Java_Main_get_1name(JNIEnv *env, jobject jobj, jint param)

{

char *buf = (char*)malloc(80);

buf = " ";

Getname(buf, 80,80);

printf("%s",buf);

//strcpy(buf, Getname(param,aux));

return env->NewStringUTF(buf);

}

but the results arelike before:

The INPUT is h //???
The FORTRAN is OH
The ARRAKI is O //?????

Message Edited by patuco on 02-07-2006 01:18 AM

Adding some comments to my previous subject is that i was performing some tests and getting all teh time the same result, only the first character is copied:

extern "C" __declspec(dllexport) char* Getname(int * value, char * string, int * stringlen);//_Getname

char *buf = (char*)malloc(10);

Getname(&parameter, buf, &i);//parameter = i = 10

SUBROUTINE GETNAME(VAL, ARRAKY)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
CHARACTER (*)ARRAKY
ARRAKY="ayudaaa"
WRITE(*,*) "The INPUT is? ", ARRAKY
END SUBROUTINE GETNAME

And another point, after leaving the fortran code the value is not saved (for the moment only one character)!!!!! I thought iwas passing the parameter by reference.

Message Edited by patuco on 02-07-2006 05:05 AM

Adding to the last comment, after leaving the fortran dll the value of the char^* is not saved, when i thought i was passing it by reference ????

buf should go by reference, but not buflen. Remove the *.

Jugoslav
www.xeffort.com

...also, DEC$ATTRIBUTES C implies call-by-value for scalar arguments (but not for strings and arrays). !DEC$ATTRIBUTES C, REFERENCE implies call by reference. However, hidden string length is never passed by reference.

Jugoslav
www.xeffort.com

before trying

extern "C" __declspec(dllexport) char* Getname(int *molecule, char * string, int *stringlen);//_Getname

i tryed with

extern "C" __declspec(dllexport) char* Getname(int molecule, char * string, int stringlen);//_Getname

but getting the same result, on ly the first char is copied and what i found after leaving the fortran it is not actualized. Could it be the C decalaration, so instead of it i should used stdcall?

I am getting crazy.... i do not know what is going on with this char *???

By the way, thanks a lot for your help ok?

I forgot it's CVF 6.0, not IVF. In CVF, the string length comes immediately after string, not at the end of the list. Thus,


extern "C" __declspec(dllimport) void
Getname(int molecule, char* string, int stringlen);//_Getname

is paired with

subroutine Getname(molecule, string)
!DEC$ATTRIBUTES C, DLLEXPORT, ALIAS:"_Getname":: Getname
integer molecule
character(*) string

WRITE(*,*) LEN(string)
Jugoslav
www.xeffort.com

I tryed your suggestion and i get a result which makes mescare.

Output

1
he INPUT MOLECULE is? |

Using only LEN to obtain the length of the array passed is only 1 !!??

i think the parameter definition and implementation is ok, isnt it?

extern "C" __declspec(dllimport) void Getname(int molecule, char * string, int stringlen);

Implementation

int i = 15;//length of the vector

int parameter = 5;//to access the 5th element in fortran

char *buf = (char*)malloc(i);

buf = " ";

printf("--C-- buffer: %s
",buf);

Getname(parameter, buf, i);

printf("
-- C --REturned buf: %s
", buf);

jstring jstrBuf = env->NewStringUTF(buf);

return jstrBuf;

by the way, why instead fo dllexport, dllimport??

i tryed another test and the same

SUBROUTINE GETNAME(VAL, ARRAKY)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
CHARACTER (*)ARRAKY
ARRAKY="ayudaaa"
ARRAKY= TRIM(ARRAKY)//CHAR(0)
WRITE(*,*) LEN(ARRAKY)
write(*,*) "The INPUT MOLECULE is? ", ARRAKY
END SUBROUTINE GETNAME

output:

1
The INPUT MOLECULE is? a

adding to the last comment where i explain the results obtained

i am trying another thing using de atributes value and reference, as follows:

SUBROUTINE GETNAME(VAL, ARRAKY)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
!MS$ATTRIBUTES VALUE :: VAL
!MS$ATTRIBUTES REFERENCE :: ARRAKY
CHARACTER *48 ARRAKY
cARRAKY="ayudaaa"
cARRAKY= TRIM(ARRAKY)//CHAR(0)
WRITE(*,*) LEN(ARRAKY)
write(*,*) "The INPUT MOLECULE is? ", ARRAKY

now the output of the length is what i specified in the declaration !!????

and another thing is that each time i tryed to copy values im gettin an error.

eventhough defininig the buffer as :

const int i = 15;

char buf[i];

the output is the same as i commented:

--C--buffer:
--C --Calling native
1
The INPUT MOLECULE is? ?
-- C --REturned buf:

The next-to-last version looks OK. You shouldn't hard-code string length in Fortran, as in the last version that "overrides" the length passed by caller, and you can easily end up overwriting something that you shouldn't.

Sorry, I can't spot anything wrong with the next-to-last version.

Jugoslav
www.xeffort.com

which of the versions are you talking about? i paste a couple and i don`t get why all the time the length of the parameter is 1

Never mind. My bad I thought that !DEC$ATTRIBUTES C does not affect how string arguments are passed; however, it does... grrr...

It appears that !DEC$ATTRIBUTES C also implies that strings are passed by value (!). I don't know why on Earth would anyone want to do that, but that's how it's implemented.

So, you should specify REFERENCE for the string argument, and pass the length explicitly:

 SUBROUTINE GETNAME(VAL, ARRAKY, iLen)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
!MS$ATTRIBUTES REFERENCE:: Arraky
INTEGER val
CHARACTER(iLen) ARRAKY
ARRAKY="ayudaaa"
ARRAKY= TRIM(ARRAKY)//CHAR(0)
WRITE(*,*) LEN(ARRAKY)
write(*,*) "The INPUT MOLECULE is? ", ARRAKY
END SUBROUTINE GETNAME

extern "C" __declspec(dllimport) void
Getname(int molecule, char* string, int len);

Btw, __declspec(dllimport) is needed (but can be omitted) because you're importing the symbol from another dll.

Jugoslav
www.xeffort.com

MS did it that way so DVF followed suit.

Steve - Intel Developer Support

just a dummy question about your implementation:

i suppose it is neccesary to define the parameter iLen as integer isnt it?

SUBROUTINE GETNAME(VAL, ARRAKY, iLen)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
!MS$ATTRIBUTES REFERENCE:: Arraky
INTEGER val, iLen
CHARACTER(iLen) ARRAKY

i comment it cuz im trying the suggestion and teh compiler is asking me for the iLen (I am using the Microsoft Developer Studio, as you said a couple years old).

After adding teh decalration of the iLen:

SUBROUTINE GETNAME(VAL, ARRAKY,LEN)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
!MS$ATTRIBUTES REFERENCE :: ARRAKY
INTEGER VAL,LEN
CHARACTER (LEN) ARRAKY
ARRAKY= "ayudaaaaaaa"
ARRAKY= TRIM(MOLECULE(VAL))//CHAR(0)
WRITE(*,*) LEN(ARRAKY)
WRITE(*,*) "The ARRAKI is ", ARRAKY
END SUBROUTINE GETNAME

and compiling the result is:

Compiling Fortran...
E:Proyectofortranmlvginterface_get.for
Assertion failed: ch_len != NULL, file err_genex.c, line 3741

abnormal program termination
Error executing fl32.exe.
mlvg.dll - 1 error(s), 0 warning(s)

Len argument is not necessary, but you have to give the string length one way or another. It looks like a compiler bug works fine on my CVF 6.6C.

Which compiler is it, by the way "Microsoft Developer Studio" is not the compiler but the IDE? You should see the CVF version on Help/About legitimate versions can be 5.0, 5.0D, 6.0, 6.1 etc.

Jugoslav
www.xeffort.com

First of all, gracias, it is working but ill show you something strange right now. Thanks you guys for your help.

ok the code which is working on my comp. is as follows:

SUBROUTINE GETNAME(VAL, ARRAKY, i_Len)
!MS$ATTRIBUTES DLLEXPORT,C,ALIAS:'_Getname'::GETNAME
!MS$ATTRIBUTES REFERENCE :: ARRAKY
INTEGER VAL, i_Len
cCHARACTER(i_Len) ARRAKY not working!!!
CHARACTER(48) ARRAKY
ARRAKY="working?"
ARRAKY= TRIM(ARRAKY)//CHAR(0)
WRITE(*,*) LEN(ARRAKY)
WRITE(*,*) "The ARRAKI is ", ARRAKY
END SUBROUTINE GETNAME

the wrapper:

const int i = 48;

int parameter = param;

char buf[i];

printf("--C-- buffer: %s
",buf);

Getname(param,buf, i);

printf("
-- C --Returnbuf: %s
", buf);

jstring jstrBuf = env->NewStringUTF(buf);

return jstrBuf;

output:

--C --buf: //only rubbish
48
The ARRAKI is working?
-- C --Returnbuf: working?
JAVA value: working?

so as you can observed it works because of the same value of teh length of the array. I think it is necessary but how to pass it, i do not know yet, but i will make a couple of tests, and i let you know what happend. If you have any dea how can be used the last parameter, let me know, I am really far from what you know.

buf = " ";

doesn't do the "obvious" thing in C. You need strcpy(buf, "Whatever"); instead.

As for the length problem, try passing Len by reference (int* + DEC$ATTRIBUTES reference) maybe that will "cheer up" the compiler ;-).

Jugoslav
www.xeffort.com

Hi,

i was thinking about the implementation of the code im using and im considering the idea of changing the calls, i mean instead of using the format:

extern "C" __declspec(dllexport) void Initapp();

use the stdcall, but i do not know how to do and how it will affect the fortran calls, specially the function described before, the one which returns the char *.

Any suggestion?

There is no compelling reason for a change, other than (as far as I know) stdcall is callable from Visual Basic while cdecl is not.

The change will (erm, should) not affect how arguments are passed; !DEC$ATTRIBUTES STDCALL and C have very similar semantics. All you have to do is to change ALIASes to include appropriate @n suffixes and use __stdcall on C++ side.

Please read the CVF help page on !DEC$ATTRIBUTES carefully. I find the semantics and order of application of attributes confusing (as you saw, string-passed-by-value got myself confused as well; For what it's worth, I filled in a "feature request" for a change of the behavior), but most of it is heritage from PowerStation from 1994. or so.

Jugoslav
www.xeffort.com

Hi again,

there is an error i have no idea what is mean and why it is produced after checking the libraries with the dependancy walker. It happens both stdcall or c libraries declarations

Anyone any idea?

Simply, it can't find msjava.dll. On my computer, it is located in C:WindowsSystem32, but I think it doesn't come by default with the system anymore.

http://www.microsoft.com/mscorp/java/faq.asp

They don't seem to support Microsoft VM for Java anymore as a part of the deal with Sun. You can still find the package lurking around on the internet, but apparently not on MS website:

http://www.google.co.uk/search?q=msjavx86.exe&start=0&ie=utf-8&oe=utf-8

Jugoslav
www.xeffort.com

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?

Pages

Leave a Comment

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