- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am playing, for a valid reason, with the grammar checker program LINK developed at Carn Mellon in about 2005. There is a later version but it does not play well with INTEL C or VS and the 2005 does what I want it to do for the moment.
The program runs quite nicely and well give me a 1 for a valid sentence and a 0 otherwise.
However, I want to add a Fortran subroutine to do a lot of hard lifting in a language I know how to code in - somewhat - and I have no desire to push my C knowledge beyond what it currently is - about Miss Scotman's first grade class level.
I have used the INTEL sample, but it is CPP, and the CM code is just pure old fashioned C.
I get a two errors, Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol _for_CFI_establish referenced in function _main Baker C:\Users\macne\Documents\Visual Studio 2017\Projects\Program111 - Baker\Baker\Baker\AMain.obj : 1
and
Severity Code Description Project File Line Suppression State
Error LNK1120 1 unresolved externals Baker C:\Users\macne\Documents\Visual Studio 2017\Projects\Program111 - Baker\Baker\Debug\Baker.exe : 1
---------------------------------------------------------------------------------------------------------
from calling the Fortran subroutine, which in the Intel sample is in a CPP file.
I tried several alternatives Fortran calling C and it basically always breaks down on the use of C files, but I do not want to stuff with the things that are working.
I enclose the complete solution - but here is the main code for the C code calling the Fortran subroutine.
/********************************************************************************/
/* Copyright (c) 2004 */
/* Daniel Sleator, David Temperley, and John Lafferty */
/* All rights reserved */
/* */
/* Use of the link grammar parsing system is subject to the terms of the */
/* license set forth in the LICENSE file included with this software, */
/* and also available at http://www.link.cs.cmu.edu/link/license.html */
/* This license allows free redistribution and use in source and binary */
/* forms, with or without modification, subject to certain conditions. */
/* */
/********************************************************************************/
#include "link-includes.h"
#include "ISO_Fortran_binding.h"
void fsub
(int INT_ARG,
CFI_cdesc_t *STR_IN,
CFI_cdesc_t *STR_OUT
);
int main() {
Dictionary dict;
Parse_Options opts;
Sentence sent;
Linkage linkage;
char * diagram;
int i, num_linkages;
char * input_string[] = {
"Grammar is useless because there, is nothing to say -- Gertrude Stein.",
"Computers are useless; they can only give you answers -- Pablo Picasso."};
char instring[40];
char outstring[40];
int intarg;
CFI_CDESC_T(0) instring_desc, outstring_desc; // Ignore warning for zero-sized array
int status;
opts = parse_options_create();
dict = dictionary_create("4.0.dict", "4.0.knowledge", NULL, "4.0.affix");
for (i=0; i<2; ++i) {
sent = sentence_create(input_string[i], dict);
num_linkages = sentence_parse(sent, opts);
if (num_linkages > 0) {
linkage = linkage_create(0, sent, opts);
printf("%s\n", diagram = linkage_print_diagram(linkage));
string_delete(diagram);
linkage_delete(linkage);
}
sentence_delete(sent);
}
dictionary_delete(dict);
parse_options_delete(opts);
strcpy(instring, "Testing...");
intarg = 123;
/*
Initialize descriptors. We'll set the length of the input string to the NUL-terminated length,
which will be picked up by Fortran.
*/
status = CFI_establish(
(CFI_cdesc_t *)&instring_desc, // Descriptor
&instring, // Base address
CFI_attribute_other, // Not allocatable or pointer
CFI_type_char, // Character type
strlen(instring), // Element size
0, // Number of dimensions (0 = scalar)
NULL // Extents (not used here)
);
status = CFI_establish((CFI_cdesc_t *)&outstring_desc, &outstring, CFI_attribute_other, CFI_type_char, sizeof(outstring), 0, NULL);
/* Call Fortran routine, passing descriptors. Note that intarg is passed by value */
fsub(intarg, (CFI_cdesc_t *)&instring_desc, (CFI_cdesc_t *)&outstring_desc);
printf("%s\n", outstring); // Should print "Testing...0123"
return 0;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Baker (the C++ project) doesn't link to the Fortran project's output library, so it's not pulling in the ifort run-time library. Ordinarily I would tell you to make FortranLib a dependent of Baker (which you should anyway), but Visual Studio won't pick up a Fortran output in a C++ project. Put the path to the .lib in Baker's Linker > Input > Additional Dependencies.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Baker (the C++ project) doesn't link to the Fortran project's output library, so it's not pulling in the ifort run-time library. Ordinarily I would tell you to make FortranLib a dependent of Baker (which you should anyway), but Visual Studio won't pick up a Fortran output in a C++ project. Put the path to the .lib in Baker's Linker > Input > Additional Dependencies.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
It took a minute to work out to include the file name in the path.
Thanks it works a treat.
Just one wonders why we need to take that step.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As I wrote above, if you had made the Fortran_Lib project a dependent of Baker, then VS should have included the .lib in the link of Baker. But a few releases ago, Microsoft changed VS so that C++ projects dependent on non-C++ projects didn't do this. In addition, a C++ DLL project won't automatically link into a Fortran project (but a C++ LIB will.)
I'm surprised you didn't also get an error for the Fortran routine not being found.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I used the sample from Intel and worked backwards slowly, it took quite a few starts to get close.
How do I make the Fortan lib a dependence on the C++ program, I have no idea, I just followed the Intel example.
The C++ print function takes the 123 string and prints 00123 - which is interesting.
The idea is simple - construct a sentence from English words and see if it is a acceptable sentence then we do some other stuff.
it may work and it may not.
But it is fun just trying.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In a solution with more than one project, right click on the project you want to be the "parent" and select Build Dependencies > Project Dependencies. Check the box for the dependent project.
I don't see leading zeroes in the output when I try it. I would not expect those from the %i specifier.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks, that worked.
Two leading zeros after Testing...
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The programmer wrote
printf("%s\n", outstring); // Should print "Testing...0123"
next question - why does the VS IDE give errors on the standard strcpy type C functions.
I know this is Fortran -- but I think I have a better chance here than the C++ Forum. They are not as busy and the answers tend to terse.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You must be working from a different sample than I see, and I wrote this sample!
The C code in the Fortran_Calls_C sample has:
sprintf_s(output_text,output_text_len,"%s%i ",input_text,int_arg);
There is no comment about what the output should be.
The reason that the compiler warns you about printf is that it is subject to buffer overflow safety issues. Therefore I put in sprintf_s, which passes the size of the output buffer rather than relying on the variables and formats to be the correct size.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I just downloaded the zip file with Baker in it. The main c routine has the following form and the last lines show the printout of the results from the fsub routine.
/********************************************************************************/
/* Copyright (c) 2004 */
/* Daniel Sleator, David Temperley, and John Lafferty */
/* All rights reserved */
/* */
/* Use of the link grammar parsing system is subject to the terms of the */
/* license set forth in the LICENSE file included with this software, */
/* and also available at http://www.link.cs.cmu.edu/link/license.html */
/* This license allows free redistribution and use in source and binary */
/* forms, with or without modification, subject to certain conditions. */
/* */
/********************************************************************************/
#include "link-includes.h"
#include "ISO_Fortran_binding.h"
void fsub
(int INT_ARG,
CFI_cdesc_t *STR_IN,
CFI_cdesc_t *STR_OUT
);
int main() {
Dictionary dict;
Parse_Options opts;
Sentence sent;
Linkage linkage;
char * diagram;
int i, num_linkages;
char * input_string[] = {
"Grammar is useless because there, is nothing to say -- Gertrude Stein.",
"Computers are useless; they can only give you answers -- Pablo Picasso."};
char instring[40];
char outstring[40];
int intarg;
CFI_CDESC_T(0) instring_desc, outstring_desc; // Ignore warning for zero-sized array
int status;
opts = parse_options_create();
dict = dictionary_create("4.0.dict", "4.0.knowledge", NULL, "4.0.affix");
for (i=0; i<2; ++i) {
sent = sentence_create(input_string[i], dict);
num_linkages = sentence_parse(sent, opts);
if (num_linkages > 0) {
linkage = linkage_create(0, sent, opts);
printf("%s\n", diagram = linkage_print_diagram(linkage));
string_delete(diagram);
linkage_delete(linkage);
}
sentence_delete(sent);
}
dictionary_delete(dict);
parse_options_delete(opts);
strcpy(instring, "Testing...");
intarg = 123;
/*
Initialize descriptors. We'll set the length of the input string to the NUL-terminated length,
which will be picked up by Fortran.
*/
status = CFI_establish(
(CFI_cdesc_t *)&instring_desc, // Descriptor
&instring, // Base address
CFI_attribute_other, // Not allocatable or pointer
CFI_type_char, // Character type
strlen(instring), // Element size
0, // Number of dimensions (0 = scalar)
NULL // Extents (not used here)
);
status = CFI_establish((CFI_cdesc_t *)&outstring_desc, &outstring, CFI_attribute_other, CFI_type_char, sizeof(outstring), 0, NULL);
/* Call Fortran routine, passing descriptors. Note that intarg is passed by value */
fsub(intarg, (CFI_cdesc_t *)&instring_desc, (CFI_cdesc_t *)&outstring_desc);
printf("%s\n", outstring); // Should print "Testing...0123"
return 0;
}
I have not changed it - whilst you showed me how to fix the problem.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page