- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Well, I am using modules in mixed language programming, in which I followed the example from the programmer's guide:
!f90 main
program main
use EXAMP
implicit none
call test
end program main
!f90 module
module EXAMP
INTERFACE
SUBROUTINE CPROG
!MS$ATTRIBUTES C, ALIAS: '_cprog' :: CPROG
END SUBROUTINE CPROG
END INTERFACE
!MS$ATTRIBUTES C:: EXAMP
TYPE MYDATA
INTEGER N
REAL X
CHARACTER(4) NAME
END TYPE MYDATA
CONTAINS
SUBROUTINE test
list%N = 10
list%X = 0.99
list%NAME = 'mary'
call CPROG
END SUBROUTINE test
END MODULE EXAMP
!c subroutines
__declspec(dllexport)
#include
#include
extern struct{
int N;
float X;
char name[4];
}EXAMP_mp_MYDATA;
void cprog(){
printf("N = %d ",EXAMP_mp_MYDATA.N);
printf("N = %f ",EXAMP_mp_MYDATA.X);
printf("N = %s ",EXAMP_mp_MYDATA.name);
}
This doesn't work. And it had the error:
"LNK2001: unresolved external symbol _EXAMP_mp_MYDATA
Please let me know if anyone of you have any suggestion or experience of solving it.
THanks.
marywah
!f90 main
program main
use EXAMP
implicit none
call test
end program main
!f90 module
module EXAMP
INTERFACE
SUBROUTINE CPROG
!MS$ATTRIBUTES C, ALIAS: '_cprog' :: CPROG
END SUBROUTINE CPROG
END INTERFACE
!MS$ATTRIBUTES C:: EXAMP
TYPE MYDATA
INTEGER N
REAL X
CHARACTER(4) NAME
END TYPE MYDATA
CONTAINS
SUBROUTINE test
list%N = 10
list%X = 0.99
list%NAME = 'mary'
call CPROG
END SUBROUTINE test
END MODULE EXAMP
!c subroutines
__declspec(dllexport)
#include
#include
extern struct{
int N;
float X;
char name[4];
}EXAMP_mp_MYDATA;
void cprog(){
printf("N = %d ",EXAMP_mp_MYDATA.N);
printf("N = %f ",EXAMP_mp_MYDATA.X);
printf("N = %s ",EXAMP_mp_MYDATA.name);
}
This doesn't work. And it had the error:
"LNK2001: unresolved external symbol _EXAMP_mp_MYDATA
Please let me know if anyone of you have any suggestion or experience of solving it.
THanks.
marywah
Link Copied
8 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
All I can think of is that you're not linking against the .OBJ created when the module was compiled.
Steve
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see that (s)he's trying to export the name which is type declaration, not a variable of given type. I suspect that variable List is the candidate for exporting. Probably the OP confused usage of TYPEs and COMMONs in this regard; COMMON declares an entity, but TYPE does not -- it's just a "template". You have to declare a variable of TYPE(MyType) and export it.
Jugoslav
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I really should teach myself to read more slowly...
You're right, Jugoslav, the code doesn't export a variable. Furthermore, there's a ATTRIBUTES C directive for the module name, which does nothing.
Steve
You're right, Jugoslav, the code doesn't export a variable. Furthermore, there's a ATTRIBUTES C directive for the module name, which does nothing.
Steve
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve & Jugoslav, thanks so much for all of your ideas.
Jugoslav, you're right. I'm trying to export the variable "list" of type "MYDATA". I'd no idea that the code is not working - I just followed the example given by the book "Programmer's Guide". Plus, I am inexperienced about it.
I modified the code as below:
!f90 code
MODULE EXAMP
...
TYPE MYDATA
INTEGER N
REAL X
CHARACTER(4) NAME
END TYPE MYDATA
TYPE(MYDATA), POINTER :: LIST
CONTAINS
SUBROUTINE test
LIST%N = 10
LIST%X = 0.99
LIST%NAME = 'mary'
call CPROG
END SUBROUTINE test
END MODULE EXAMP
!end f90 code
!c subroutines
__declspec(dllexport)
#include
#include
extern struct{
int N;
float X;
char name[4];
}EXAMP_mp_LIST;
void cprog(){
printf("N = %d ",EXAMP_mp_LIST.N);
printf("X = %f ",EXAMP_mp_LIST.X);
printf("Name = %s ",EXAMP_mp_LIST.name);
}
!
Well, there's no more error, HOWEVER, the program didn't print out the content of the variables correctly. It prints:
N = 3151408
X = 0.000000
Name =
DO YOU HAVE ANY IDEA WHY?
BTW., I'm a "She"... hee..
Again, thanks so much.
marywah.
Jugoslav, you're right. I'm trying to export the variable "list" of type "MYDATA". I'd no idea that the code is not working - I just followed the example given by the book "Programmer's Guide". Plus, I am inexperienced about it.
I modified the code as below:
!f90 code
MODULE EXAMP
...
TYPE MYDATA
INTEGER N
REAL X
CHARACTER(4) NAME
END TYPE MYDATA
TYPE(MYDATA), POINTER :: LIST
CONTAINS
SUBROUTINE test
LIST%N = 10
LIST%X = 0.99
LIST%NAME = 'mary'
call CPROG
END SUBROUTINE test
END MODULE EXAMP
!end f90 code
!c subroutines
__declspec(dllexport)
#include
#include
extern struct{
int N;
float X;
char name[4];
}EXAMP_mp_LIST;
void cprog(){
printf("N = %d ",EXAMP_mp_LIST.N);
printf("X = %f ",EXAMP_mp_LIST.X);
printf("Name = %s ",EXAMP_mp_LIST.name);
}
!
Well, there's no more error, HOWEVER, the program didn't print out the content of the variables correctly. It prints:
N = 3151408
X = 0.000000
Name =
DO YOU HAVE ANY IDEA WHY?
BTW., I'm a "She"... hee..
Again, thanks so much.
marywah.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Because you declared it as a POINTER. (And, btw, I don't see that you allocated it or associated it, so it's strange you didn't get a big kaboom). 3151408 happens to be the address of your actual List variable :-).
...and, also, take care the C strings must be CHAR(0)-terminated, while Fortran's don't. Thus, you have to reserve an additional character in name field:
...
TYPE MYDATA
INTEGER N
REAL X
CHARACTER(5) NAME
END TYPE MYDATA
...
LIST%NAME = 'mary'C ! or LIST%NAME = 'mary'//CHAR(0)
Regards
Jugoslav
...and, also, take care the C strings must be CHAR(0)-terminated, while Fortran's don't. Thus, you have to reserve an additional character in name field:
...
TYPE MYDATA
INTEGER N
REAL X
CHARACTER(5) NAME
END TYPE MYDATA
...
LIST%NAME = 'mary'C ! or LIST%NAME = 'mary'//CHAR(0)
Regards
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
jugoslav, thanks for reminding me that the declaration is a POINTER. Now, it's WORKING.
OH, I actually have the allocation in the program but I missed it when I typed the message.
I'm going to try to include the pionter to the type in fortran and access it by the pointer to the struct in c. Do you think it's durable?
You guys are very helpful!
Thanks so much.
marywah.
OH, I actually have the allocation in the program but I missed it when I typed the message.
I'm going to try to include the pionter to the type in fortran and access it by the pointer to the struct in c. Do you think it's durable?
You guys are very helpful!
Thanks so much.
marywah.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Generally speaking, C pointers and Fortran pointers are not semantically identical and cannot be portably used as means for interchange between the languages. However, underlying CVF implementation of scalar pointers is the same as in C -- 4-byte address, so you can use them within the same C/Fortran structures (but beware that this may not be portable to other compilers). That includes pointers to strings (CHARACTER(LEN=n)).
Pointers to arrays are a different beast, though. Fortran array pointers have richer semantics than C ones (e.g. you can point to a non-contiguous array section in Fortran, but not in C). Search for "Array descriptor" in Programmer's Guide, and you'll find description of CVF array pointers (IIRC, they're 28 bytes long for 1-dimension array). Alternatively, you can use "Cray" or "Integer" pointers on Fortran side, which look more like C pointers, but they're not quite portable either, and are a bit ugly to use.
Jugoslav
Pointers to arrays are a different beast, though. Fortran array pointers have richer semantics than C ones (e.g. you can point to a non-contiguous array section in Fortran, but not in C). Search for "Array descriptor" in Programmer's Guide, and you'll find description of CVF array pointers (IIRC, they're 28 bytes long for 1-dimension array). Alternatively, you can use "Cray" or "Integer" pointers on Fortran side, which look more like C pointers, but they're not quite portable either, and are a bit ugly to use.
Jugoslav
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Jugoslva, I really learn a lot about accessing data between c and fortran. Now it's more clear to me how to integrate a piece of c code to the fortran code.
cheers,
marywah.
cheers,
marywah.

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page