Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

How to solve the error LNK1120....

marywah
Beginner
1,475 Views
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


0 Kudos
8 Replies
Steven_L_Intel1
Employee
1,475 Views
All I can think of is that you're not linking against the .OBJ created when the module was compiled.

Steve
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,475 Views
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
0 Kudos
Steven_L_Intel1
Employee
1,475 Views
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
0 Kudos
marywah
Beginner
1,475 Views
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.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,475 Views
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
0 Kudos
marywah
Beginner
1,475 Views
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.
0 Kudos
Jugoslav_Dujic
Valued Contributor II
1,475 Views
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
0 Kudos
marywah
Beginner
1,475 Views
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.
0 Kudos
Reply