- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hello every one,
I’m developing an upgrade from Visual Fortran 6.0 to Visual Studio 2013. I want to create a dynamic library based on the C++ project (dependent of the fortran project) but I am having a linking error. (Building Fortran project like static and C++ project like dynamic libraries)
Error
error LNK2001: unresolved external symbol _block error LNK2019: unresolved external symbol _block referenced in function "public: int __thiscall Data::Initialize(void)" (?Initialize@Data@@QAEHXZ)
The linking error comes because I am trying to load the address of a fortran common block defined in a fortran header in a C++ header.
I will put and example, some how like I have in my project:
Fortran header(fheader.cn)
INTEGER & & I_A REAL & & R_A, & R_B, & R_C COMMON /BLOCK/ & & I_A, & R_A, & R_B, & R_C
C++ Header (cheader.h)
... extern "C" { void* block(); } ... class Data { public: BOOL Initialize() { Define(block, "block.i_a",XX,YY); Define(block, "block.r_a",XX,YY); Define(block, "block.r_b",XX,YY); Define(block, "block.r_c",XX,YY); } void Define(void* address, const char* path,XX,YY); ...
Calling convention: C REFERENCE on Fortran project and __cdecl on C++ project.
I knwo that I need to make some export to the common block, but I don't know how to do it in a statick library.
Thank you in advance,
Ibon
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You can only "call" code entry points, not data symbols, whereas you seem to be attempting to blur the distinction between code and data.
If you want your code to be portable, please use the ISO Fortran-C interoperability features of Fortran 2003 and later. Instead of using troublesome COMMON blocks, you could consider declaring the variables to be exported in a module instead.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for you fast reply. I am not used to new Fortran lenguages... Can you give a example of how can I do it or a link with a example, please?
Thank you so much!
Ibon
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
So that we can narrow down the scope of which approach to choose, please expand on what you want to do with the shared data.
There are some example of mixed language programs provided with the Intel Fortran distribution. For example, see <Intel Fortran compiler directory>\samples_2016\en\compiler_f\psxe\MixedLanguage.zip, and assess whether you can adapt one of those examples for your purposes.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In case it wasn't clear, iso_c_binding does support labeled common blocks, so the recommendation to use it isn't by itself sufficient reason to change away from common.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
iso_c_binding supports COMMON label, but I need to export it to a C++ project, and just right now it is not working in C++ projects only in the fortran proejct... I using the same schema in all commons: Define the type and add to a common label. All are missing :(
This shared data is supposed to be defined and initialized in fortran project and then modified by C++ project... That's why I want to catch the address of the common to use it like pointer then to have easy access to the different variables. And there are a lot of variables to start coding all off them like structures in C....
Watching the examples, it is using subroutines to call fortran from C++... Can I do same using modules?
The project that I am trying to build is long and old, it is written on fortran 77, can I mix it with 2003 and later interoperability features?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Assume Fortran and C++ are called in the same task, you may solve your problem as:
- get the COMMON address by using addr = LOC(1st common var)
- pass this value to C++ (there are a number of ways)
- cast the address to a structure reproducing the COMMON variables.
A COMMON structure is one of best features in Fortran.
Regards
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran 2003 is (largely) compatible with FORTRAN 77 - a few features have been deleted from the standard and others are deprecated, but that should not really matter: compilers are very unlikely to actually remove them unless you ask for a particular standard.
So even with FORTRAN 77 code you can use the ISO_C_BINDING module, provided you use a Fortran 2003 compliant compiler.
That said, modules are a Fortran feature. The C++ compiler does not understand them. You will have to work around that limitation. The way to do that is to have C++ call a Fortran routine that is outside any module, but that accesses via USE the module or modules you need.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
arjenmarkus wrote:Variables and procedures in a module, that have a language binding spec (BIND(C)) can be referenced/called directly from C++. There is no need to use an external procedure as an intermediate.
Fortran 2003 is (largely) compatible with FORTRAN 77 - a few features have been deleted from the standard and others are deprecated, but that should not really matter: compilers are very unlikely to actually remove them unless you ask for a particular standard.
So even with FORTRAN 77 code you can use the ISO_C_BINDING module, provided you use a Fortran 2003 compliant compiler.
That said, modules are a Fortran feature. The C++ compiler does not understand them. You will have to work around that limitation. The way to do that is to have C++ call a Fortran routine that is outside any module, but that accesses via USE the module or modules you need.
Edit to add a little example of C++ code referencing Fortran common variables using the Fortran-C interoperability feature of Fortran 2003.
#include <iostream> extern "C" struct { float a; float b[2]; int c; } fred; extern "C" void c_function() { std::cout << "fred.a = " << fred.a << std::endl; std::cout << "fred.b[0] = " << fred.b[0] << std::endl; std::cout << "fred.b[1] = " << fred.b[1] << std::endl; std::cout << "fred.c = " << fred.c << std::endl; }
PROGRAM p USE ISO_C_BINDING, ONLY: C_INT, C_FLOAT IMPLICIT NONE COMMON /fred/a,b,c BIND(C,NAME='fred') :: /fred/ REAL(C_FLOAT) :: a, b(2) INTEGER(C_INT) :: c INTERFACE SUBROUTINE C_FUNCTION() BIND(C,NAME='c_function') END SUBROUTINE C_FUNCTION END INTERFACE a = 1.0 b = [2.0, 3.0] c = 4 CALL C_FUNCTION END PROGRAM p
>cl /c /EHsc /W3 "2015-09-15 common-c.cpp" Microsoft (R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64 Copyright (C) Microsoft Corporation. All rights reserved. 2015-09-15 common-c.cpp >ifort /check:all /warn:all /standard-semantics "2015-09-15 common-f.for" "2015-09-15 common-c.obj" Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 16.0 Build 20150815 Copyright (C) 1985-2015 Intel Corporation. All rights reserved. Microsoft (R) Incremental Linker Version 10.00.40219.01 Copyright (C) Microsoft Corporation. All rights reserved. "-out:2015-09-15 common-f.exe" -subsystem:console "2015-09-15 common-f.obj" "2015-09-15 common-c.obj" >"2015-09-15 common-f.exe" fred.a = 1 fred.b[0] = 2 fred.b[1] = 3 fred.c = 4
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Argh, of course. Thinking too much of the old way.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for all your replies! I am understanding how could I solve my problem... But I have a question... If fortran project (with the common block) is compiled in a static library, it should have a address somewhere over the address map of the library. Then, can I call to common block address from a void pointer?
Like:
extern "C" void* comm_block_name;
Or it must be defined, because god standard says that, like structure?
Thank you so much :D
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ibon D. wrote:
Thanks for all your replies! I am understanding how could I solve my problem... But I have a question... If fortran project (with the common block) is compiled in a static library, it should have a address somewhere over the address map of the library. Then, can I call to common block address from a void pointer?
Like:
extern "C" void* comm_block_name;Or it must be defined, because
godstandard says that, like structure?Thank you so much :D
I think your declaration would end up interpreting the contents of the common block as a void pointer. You would want something like:
extern "C" struct { int dummy; } comm_block_name; void* comm_block_address = &comm_block_name;
As mentioned by others up-thread, I do not understand why you want to "call" the common block address.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
ianh wrote:
As mentioned by others up-thread, I do not understand why you want to "call" the common block address.
Because it is an old and big project that I am trying to upgrade to newest versions (VS2013) and I want to change as less lines as I can (I have a thousand of common blocks, I want to wast as less time as I can :D). The project was written for VC++6 and it is working like I explained in first post.Calling to the common block like a pointer to function, somehow like a calling to subroutine for newest standard.
Anyway, thank you so much for the help and if i need to write more code, i will do it! :)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think that the O.P. does not use the word "call" in the restricted sense used in programming. We can dip into computing history to see why this is important.
There is a concept called Harvard Architecture, in which program code and program data live in separate spaces, with highly restricted and precisely defined interactions allowed between the two. There were some hardware realizations of this architecture, but our common computers of today do not follow this design. Instead, we have conventions in software and operating systems that attempt to enforce the same kind of "separate and unequal" notion. In the early days of computing, one submitted a card deck for execution on a mainframe computer, and waited for the program printout to arrive the next day. Once in a while, we saw in our assigned output box a handwritten piece of paper instead of the expected fanfold printout, saying "PROGRAM ATTEMPTED TO EXECUTE DATA".
Here is an example of a defective program that attempts to do just that.
main(){ struct cmplx{ float x; float y; } z, w; w=z(2,3); }
Ibon D., how would you describe this program -- specifically, the way that it attempts to use z as a function?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
mecej4 wrote:
Ibon D., how would you describe this program -- specifically, the way that it attempts to use z as a function?
I will describe it like uncompilable program. You are calling a function through a structure.
I understand want you try to explain... But the old program is working like that, is not my fault. The code has more than 30 years, actually is older than me :D
I will try to found a proper solution to fix this chaos in my code and I will let you know how I do it...
Thanks,
Ibon
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
If you're going back in history, the means for making system calls in the first f77 compiler I used was to initialize a labeled COMMON to executable octal code (ending with a RET) and CALL it. Similar hacks were involved in buffer overflow exploits which delivered malware in the more recent past. As that's probably not what is meant here, use of the same terminology is misleading.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
An interesting learning experience occurred for me when, on the 8086, a C switch statement was executed and the first jump target (case xx:) happened to be fall within the six-byte instruction queue of the CPU, so the just-modified target address was never used. That was a tough debugging problem. There were similar issues with the POKE instruction provided with early Basic interpreters.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
From Microsoft documentation:
Accessing Common Blocks Directly
You can access Fortran common blocks directly by defining a structure with the appropriate fields and then declaring the structure as an external data symbol. For example, the following code defines a structure named CBLOCK, which the C code can use to directly access items in the Fortran common block named CBLOCK:
struct block_type
{
int n;
double x;
double y;
};
extern struct block_type CBLOCK;

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