forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Linking C and FTN95 under Plato IDE
Goto page 1, 2  Next
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Thu Dec 18, 2014 6:13 pm    Post subject: Linking C and FTN95 under Plato IDE Reply with quote

I must be doing something wrong, but I cannot get the "C" to link to the FTN95, no matter which calling sequence I use.

I've checked for other posts on this, but they all indicate that what I'm doing should work.

I have a large quantity of "C++" code (in .cpp files) that I have compiled into a single library. There is one interfacing function that I will call from FTN95. I have the code snippets from the FTN 95 and C-source below, along with the linker message and the runtime error. The runtime shows that it cannot call _PDFCreate, yet the linker states that PDFCreate cannot be found. It would appear that SCC is not creating the linkage name that matches the FTN name, but I can find no options in SCC compiler to force a specific name.

I've tried STDCALL and changed the "C" code to the __stdcall form, but no joy there either.

In the "C" created .LIB file that I include as reference, PDCreate appears to have several "incarnations" in naming, including "_PDFCreate__C" as well as "PDFCreate". I've tried all the logical variations, to no avail.

Any help is appreciated,
Bill

Quote:
In the FTN source:
C_EXTERNAL PDFCREATE 'PDFCreate'(STRING)
...
call PDFCREATE(TRIM(OPENED_FILENAME(I)))

In the "C" source, compiled by SCC:

extern "C" void PDFCreate(char *argv)

From the Link step:
Compilation completed with no errors.
Linking...
WARNING the following symbols are missing:
PDFCreate Z:\CMASTERF95\CheckMate\Win32\NEW_COPEN.obj
(Z:\CMASTERF95\CFUNC\NEW_COPEN.FOR)
Creating executable: CheckMate\Win32\C-MASTER.exe
Creating Linker map file: map-c-master.map
Linking completed.


Runtime error from program:z:\cmasterf95\checkmate\win32\c-master.exe
Run-time Error
*** Error 29, Call to missing routine : _PDFCreate at 0x00489bfa.


COPEN - in file new_copen.for at line 226 [+1d4f] [recur= 1]
LPCLOSE - in file lpset.for at line 80 [+00a0]
CQUADB - in file cquadbld.for at line 242 [+21ad]
XMMANT - in file cmaint.for at line 46 [+0551]
main - in file cmain.for at line 89 [+0522]
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Thu Dec 18, 2014 8:55 pm    Post subject: Reply with quote

Just to try to keep moving forward, I included the C source in the project with the FTN files. Now, it properly finds the interface routine, just like it is supposed to. However, all the called routines now can't be found.

There must be a compile option that I am not setting, or that is not available and must be CONFIG'ed to work properly.

Any suggestions?
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Thu Dec 18, 2014 9:19 pm    Post subject: Reply with quote

If I run SLINK from the command line, and simply include all my .obj files in the link, then there are no un-found symbols. So, it has to be an option missing.

Where, and what, I'll need to change, I have no idea.
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Fri Dec 19, 2014 4:17 am    Post subject: Reply with quote

So, this first trial at loading all the objects appeared to work, but didn't really.

I built a command file to load all the .obj files for the 4 projects that make up my build. Even though all the obj files are loaded, there are undefined symbols shown at link time. If I load the "missing" obj file again, the linker complains (rightly so) that there are multiply defined symbols. It doesn't identify all the symbols, just the first one it encounters, then exist with an error. If I try to also link in the library created from the object files as well, there is no change in results.

So, I am at a complete loss now. Whatever is going on is subtle, and would appear to be some bug in either the SCC, FTN95, or SLINK or SLIM.
Back to top
View user's profile Send private message Visit poster's website
jalih



Joined: 30 Jul 2012
Posts: 196

PostPosted: Fri Dec 19, 2014 10:14 am    Post subject: Re: Linking C and FTN95 under Plato IDE Reply with quote

wahorger wrote:

I have a large quantity of "C++" code (in .cpp files) that I have compiled into a single library.

Is this library compiled as DLL? If so, you only need to add a reference for the library DLL into Plato project. Just add required STDCALL or C_EXTERNAL statement into fortran code using those C-callable external functions and code should compile and link properly.

There is no need to use import libraries or handle name mangling manually, if you use Plato to build your project.
Back to top
View user's profile Send private message
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Fri Dec 19, 2014 3:40 pm    Post subject: Reply with quote

jalih,

None of the libraries were compiled as DLL's (yet). I was hoping to make life simple; apparently that didn't happen!

I've no experience with building DLL's and perhaps this might be the time to learn.

Bill
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Mon Dec 22, 2014 7:42 pm    Post subject: Reply with quote

For your first experiment you should start by paswing a REAL or an INTEGER and not a STRING. Also pass the argument as a reference. Also use only upper case letters in the name. Use C_EXTERNAL and extern "C". You will find detailed instructions in ftn95.chm under "mixed language programming".

When it comes to STRINGS, every CHARCTER argument in Fortran, has a hidden length at the end which becomes visible in C. Again details can be found in ftn95.chm.
Back to top
View user's profile Send private message AIM Address
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Dec 22, 2014 8:16 pm    Post subject: Reply with quote

I've worked out this particular problem, but it required me to move to the RELEASE compilation. (Apparently, I have a high tolerance for trying options until I find something that works.) I keep detailed records on what I try, and what I get as a result.

There are a couple of issues that are still affecting me between a CHECKMATE and RELEASE compilations. I am able to use the conditional compilation to mask the issue, but not yet solve it.

Bill
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Mon Dec 22, 2014 8:27 pm    Post subject: Reply with quote

If it doesn't work in CHECKMATE mode then there is something wrong that needs to be fixed.
Back to top
View user's profile Send private message AIM Address
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Dec 22, 2014 8:33 pm    Post subject: Reply with quote

I'll try a very simple project with a few LOC and see if I can get it to replicate.
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Dec 22, 2014 8:52 pm    Post subject: Reply with quote

Here is the test code, all in one FTN95 project (no separated projects/compiling)

First the FTN95. I used my existing calling sequence and call to the same same "C" test code.
Code:
!FTN95 application...
     PROGRAM main
     c_EXTERNAL PDFCREATE 'PDFCreate'(STRING)
     CHARACTER*30 TESTSTRING
     DATA TESTSTRING/'THIS IS A TEST STRING'/
     CALL PDFCREATE(TESTSTRING)
     END PROGRAM main


Next, the "C" code used to validate what I was doing.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" void PDFCreate(char *argv)
{
   char   *new_filename;

    printf("Source file: %s\n",argv);
   new_filename = (char *)calloc(strlen(argv)+4,1);
   strcpy(new_filename,argv);
   strcat(new_filename,".pdf");
    printf("Output file: %s\n",new_filename);

   return;
}

FYI: For CHECKMATE, you have to select the Mangle option, for RELEASE, you must not.

The CHECKMATE version give the following error:
Quote:

Runtime error from program:z:\cmasterf95\test\checkmate\win32\test.exe
Access Violation
The instruction at address 00401116 attempted to read from location f0f0f0f0 in file forttest.cpp at line 8

PDFCreate__C - in file forttest.cpp at line 8 [+0036]
main - in file main.f95 at line 6 [+007f]

eax=ffffffff ebx=0019f4d4 ecx=f0f0f0f0
edx=0360fc54 esi=00401112 edi=0360fc70
ebp=0360fc68 esp=0360fc44 IOPL=2
ds=002b es=002b fs=0053
gs=002b cs=0023 ss=002b
flgs=00010286 [NC EP NZ NS DN NV]

00401116 mov eax,[ecx]
00401118 cmp eax,0x80808080
0040111e jne 401125

The RELEASE compilation gives no error and performs as expected.
Back to top
View user's profile Send private message Visit poster's website
PaulLaidler
Site Admin


Joined: 21 Feb 2005
Posts: 7924
Location: Salford, UK

PostPosted: Mon Dec 22, 2014 10:47 pm    Post subject: Reply with quote

The C code expects the string to be null terminated so one way forward is to concatenate your Fortran character variable with char (0). This would also require passing a REF rather than a STRING.
Back to top
View user's profile Send private message AIM Address
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Dec 22, 2014 11:09 pm    Post subject: Reply with quote

From the HELP file ("Calling C/C++ from FTN95"):

Quote:
If the function uses a string data type, code is planted to generate a C/C++ style string before entering the C/C++ function. Code is also generated after the function call to convert the C style string back into a Fortran string. This frees the C/C++ programmer from the additional complexities of providing the conversion code. It also means that a Fortran programmer can call a third party library without converting all string references into C/C++ strings before calling an external routine.

and
Quote:
C_EXTERNAL COPY_STRING 'strcpy' (OUTSTRING,INSTRING): INTEGER*4
C_EXTERNAL STRNCPY 'strcat' (STRING, INSTRING(40)): INTEGER*4

where strcpy and strcat are the standard C library functions.


and those routines require null terminated "strings".

Therefore, my confusion.

I looked at the assembly code, and in the CHECKMATE and RELEASE compilation, there is a call to MAKE_CSTRING@ prior to the PDFCreate call, then the PDFCreate call, then a call to GET_CSTRING@ after the call. There are subtle differences in the assembly code between CHECKMATE and RELEASE compilations.
[/quote]
Back to top
View user's profile Send private message Visit poster's website
wahorger



Joined: 13 Oct 2014
Posts: 1217
Location: Morrison, CO, USA

PostPosted: Mon Dec 22, 2014 11:17 pm    Post subject: Reply with quote

Also, terminating the FORTRAN with a NULL string yielded the same error.

Code:
 CHARACTER*30 TESTSTRING
 character*1 NULLSTRING
 NULLSTRING = char(0)
 DATA TESTSTRING/'THIS IS A TEST STRING'/
 CALL PDFCREATE(TESTSTRING//NULLSTRING)
Back to top
View user's profile Send private message Visit poster's website
jalih



Joined: 30 Jul 2012
Posts: 196

PostPosted: Tue Dec 23, 2014 11:48 am    Post subject: Re: Reply with quote

wahorger wrote:

Next, the "C" code used to validate what I was doing.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern "C" void PDFCreate(char *argv)
{
   char   *new_filename;

    printf("Source file: %s\n",argv);
   new_filename = (char *)calloc(strlen(argv)+4,1);
   strcpy(new_filename,argv);
   strcat(new_filename,".pdf");
    printf("Output file: %s\n",new_filename);

   return;
}


There is an error in your C-code: you are allocating buffer for the filename + .pdf file extension, but forgot to add one byte for the null.

Access violation comes, when trying to write outside the buffer.

By the way, I think you can add a null-byte for the fortran string by just assigning:
Code:

character(20) :: str

str = 'This is C-string.'C
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group