Expose a Fortran variable to C - binding

I learned how to use C global variables in Fortran code, as given in the example below. But how to do it in a reverse direction, i.e., define (and initialize) a variable in Fortran and make it accessible to C?
/* C global variables */
int c_extern;
long myVariable;
!Fortran binding code
MODULE LINK_TO_C_VARS
USE ISO_C_BINDING
!Implicit label binding
!Bind variable C_EXTERN to c_extern
INTEGER(C_INT), BIND(C) :: C_EXTERN
!Explicit label binding
!Bind C2 to myVariable
INTEGER(C_LONG) :: C2
BIND(C, NAME='myVariable') :: C2
END MODULE LINK_TO_C_VARS

Follow-up:
Thanks to M.S.B.
I did some experiments. I put the C code in vars.c, the Fortran code in mod.f90.
gcc -c vars.c
nm vars.o
0000000000000004 C c_extern
0000000000000008 C myVariable
gfortran -c mod.f90
nm mod.o
0000000000000004 C c_extern
0000000000000008 C myVariable
'man nm' says: "C" -- The symbol is common. Common symbols are uninitialized data. When linking, multiple common symbols may appear with the same name. If the symbol is defined anywhere, the common symbols are treated as undefined references.
Then, I changed variables in vars.c to extern
<<vars-ext.c>>
extern int c_extern;
extern long myVariable;
gcc -c vars-ext.c and nm vars-ext.o
U c_extern
U myVariable
gfortran can successfully link mod.o with vars.o or vars-ext.o. It looks that the magic lies in the "C" kind symbols.

Related

gfortran compile warning, "may be used uninitialized" for obviously initialized array

My compiler has started giving me a warning on a part of my code I haven't touched while developing code... The zarray is allocated, set to zero, then part of the array is set to rarray that is passed in.
SUBROUTINE advection(rbox0,rfrac,rarray,na)
IMPLICIT NONE
INTEGER, INTENT(IN) :: na
REAL, INTENT(IN) :: rfrac
REAL, INTENT(IN) :: rbox0
REAL, INTENT(INOUT) :: rarray(0:na)
! local arrays
REAL, ALLOCATABLE :: zarray1(:),zarray2(:)
ALLOCATE(zarray1(-4:2*na))
zarray1(:)=0.0
zarray1(0:na)=rarray ! zarray stores the original array
rarray(:)=0.0
rarray(0)=(1.0-rbox0)*zarray1(0)
! etc etc
Now with gfortran on a mac I'm getting this compile warning:
vectri.f90:1101:38:
1101 | rarray(0)=(1.0-rbox0)*zarray1(0)
| ^
Warning: 'MEM <real(kind=4)[0:]> [(real(kind=4)[0:] *)_77][4]' may be used uninitialized [-Wmaybe-uninitialized]
In my experience, warnings such as these are ignored at your peril, but I can't for the life of me understand why the compiler is getting upset here... I'm using
GNU Fortran (Homebrew GCC 11.3.0_1) 11.3.0
EDIT: in reply to the comments below, the code was originally
zarray1=0.0
and
rarray=0.0
when the warning arose, I changed to insert (:) to see if it would help (it didn't :-( )

How does clang check redefinitions?

I'm new to Clang, and trying to write some clang-tidy checks. I want to find something that works as a "variable table", to check if some names are well-formed.
My intuition is like this:
To write redefinition code will sometimes cause an error, which is thrown out by Clang's diagnostics. like:
int main(){
int x;
int x; // error: redefinition
return 0;
}
From my perspective, clang may keep a dynamic variable table to check whether a new definition is compatible/overloading/error.
I tried to dive into clang source code and explored something:
Identifiertable, is kept by preprocessor, which marks all the identifiers, but does not do the semantic legal checking.
DeclContext, which seems to be an interface for users to use, a product produced by semantic checking.
My question is :
How Clang do the legal checking?
Am I able to get the variable table(If there exists such kind of things)?
If I cannot get such things, how could I know which variables are reachable from a location?
Thanks for your suggestions!
TLDR; see Answers below.
Discussion
All of your questions are related to one term of C standard, identifier, in C99-6.2.1-p1:
An identifier can denote an object; a function; a tag or a member of a structure, union, or
enumeration; a typedef name; a label name; a macro name; or a macro parameter.
Each identifier has its own scope, one of the following, according to C99-6.2.1-p2:
For each different entity that an identifier designates, the identifier is visible (i.e., can be
used) only within a region of program text called its scope.
Since what you are interested in are the variables inside a function (i.e., int x), then it should then obtain a block scope.
There is an process called linkage for the identifiers in the same scope, according to C99-6.2.2-p2:
An identifier declared in different scopes or in the same scope more than once can be
made to refer to the same object or function by a process called linkage.
This is exactly the one that put a constraint that there should be only one identifier for one same object, or in your saying, definition legally checking. Therefore compiling the following codes
/* file_1.c */
int a = 123;
/* file_2.c */
int a = 456;
would cause an linkage error:
% clang file_*
...
ld: 1 duplicate symbol
clang: error: linker command failed with exit code 1
However, in your case, the identifiers are inside the same function body, which is more likely the following:
/* file.c */
int main(){
int b;
int b=1;
}
Here identifier b has a block scope, which shall have no linkage, according to C99-6.2.2-p6:
The following identifiers have no linkage: an identifier declared to be anything other than
an object or a function; an identifier declared to be a function parameter; a block scope
identifier for an object declared without the storage-class specifier extern.
Having no linkage means that we cannot apply the rules mentioned above to it, that is, it should not be related to a linkage error kind.
It is naturally considered it as an error of redefinition. But, while it is indeed defined in C++, which is called One Definition Rule, it is NOT in C.(check this or this for more details) There is no exact definition for dealing with those duplicate identifiers in a same block scope. Hence it is an implementation-defined behavior. This might be the reason why with clang, the resulting errors after compiling the above codes (file.c) differs from the ones by gcc, as shown below:
(note that the term 'with no linkage' by gcc)
# ---
# GCC (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04))
# ---
$ gcc file.c
file.c: In function ‘main’:
file.c:4:6: error: redeclaration of ‘b’ with no linkage
int b=1;
^
file.c:3:6: note: previous declaration of ‘b’ was here
int b;
^
# ---
# CLANG (Apple clang version 13.0.0 (clang-1300.0.29.3))
# ---
% clang file.c
file.c:4:6: error: redefinition of 'b'
int b;
^
file.c:3:6: note: previous definition is here
int b=1;
^
1 error generated.
Answers
With all things above, I think it suffices to answer your questions:
How clang perform the definition legally checking?
For global variables, either clang or gcc would follow the C standard rules, that is to say, they handle the so-called "redefinition errors" by the process called Linkage. For local variables, it is undefined behavior, or more precisely, implementation-defined behavior.
In fact, They both view the "redefinition" as an error. Although variable names inside a function body would be vanished after compiled (you can verify this in the assembly output), it is undoubtedly more natural and helpful for letting them be unique.
Am I able to get the variable table(If there exists such kind of things)?
Having not so much knowledge about clang internals, but according to the standards quoted above, along with an analysis of compiling, we can infer that IdentifierTable might not much fit your needs, since it exists in "preprocessing" stage, which is before "linking" stage. To take a look how clang compiler deals with duplicate variables (or more formally, symbols), and how to store them, you might want to check the whole project of lld, or in particular, SymbolTable.

Why can LuaJIT/Openresty use deprecated 'arg' language feature?

My understanding is that LuaJIT uses the Lua 5.1 syntax. In Lua 5.1, the 'arg' feature was removed from the language.
However, the following code works.
// test.lua
local function foo()
for k,v in pairs(arg) do
print(k .. " " .. v)
end
end
foo()
I would expect arg to be nil, but it exists and is doing the Lua 5.0 functionality.
Running resty test.lua hello world results in:
0 test.lua
1 hello
2 world
-1 /usr/local/bin/resty
Why does this work? Are there exceptions to the 5.1 syntax that Openresty and LuaJIT can use?
You're mixing two different things.
The arg table you see here is not a "deprecated Lua feature". It's a table of arguments given to Lua interpreter, explicitly pushed to the global arg variable by the interpreter, and it's still there in the latest Lua and LuaJIT versions.
The feature you've heard was removed - that's about replacing implicit arg parameter with vararg expression in vararg functions. I.e. the extra arguments to functions now available through ... syntax, and not as a table of collected values through implicit arg parameter.

Why does the nm tool output for the extern-only and defined-only options overlap?

I'll start by giving my understanding of the options:
extern-only: Show me only those symbols which are referenced by the binary but whose definitions (the code or variable) will be provided by another binary
defined-only: Show me only those symbols whose definitions are contained in the binary.
Here are my commands and their output:
$nm -defined-only GenerationOfNow | grep FIRAZeroingWeakContainer
000000010002c128 t -[FIRAZeroingWeakContainer .cxx_destruct]
000000010002c0fb t -[FIRAZeroingWeakContainer object]
000000010002c114 t -[FIRAZeroingWeakContainer setObject:]
000000010021a218 S _OBJC_CLASS_$_FIRAZeroingWeakContainer
00000001002177f8 s _OBJC_IVAR_$_FIRAZeroingWeakContainer._object
000000010021a1f0 S _OBJC_METACLASS_$_FIRAZeroingWeakContainer
$nm -extern-only GenerationOfNow | grep FIRAZeroingWeakContainer
000000010021a218 S _OBJC_CLASS_$_FIRAZeroingWeakContainer
000000010021a1f0 S _OBJC_METACLASS_$_FIRAZeroingWeakContainer
As you can see, the -extern-only output is a subset of the -defined-only output. Why? Perhaps my question should be: What is the meaning of those items which have a S in the second column?
You're confusing -extern-only with -undefined-only.
There are two concepts that are being mixed here:
extern vs. local (in C extern vs. static, "local" is sometimes also called "private")
defined vs. undefined
The former describes the availability of a symbol while the latter describes its origin. And yes, even the notion of a private undefined symbol exists, as per man nm:
Each symbol name is preceded by its value (blanks if undefined). [...] A lower case u in a dynamic shared library indicates a undefined reference to a private external in another module in the same library.
Now, when using -undefined-only you actually do get the complement of -undefined-only
bash$ nm test.dylib
0000000000000f60 T _derp
0000000000000f70 t _herp
U _printf
U dyld_stub_binder
bash$ nm -defined-only test.dylib
0000000000000f60 T _derp
0000000000000f70 t _herp
bash$ nm -undefined-only test.dylib
_printf
dyld_stub_binder
bash$ nm -extern-only test.dylib
0000000000000f60 T _derp
U _printf
U dyld_stub_binder
-extern-only does not seem to have a complementary flag however.

How to define multiple c flags in ios?

In Build settings, at custom compiler Flags, how can i declare two other C flags names?
For example:
Other C Flags: -DEXAMPLE
I tried:
Other C Flags: -DEXAMPLE, -DEXAMPLE2
-DEXAMPLE2 is not working. How can i declare multiple C Flags?
Drop the comma, each -D is its own argument to the compiler:
-DEXAMPLE -DEXAMPLE2

Resources