Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify which C version external functions use #1088

Closed
modelica-trac-importer opened this issue Nov 4, 2018 · 22 comments
Closed

Specify which C version external functions use #1088

modelica-trac-importer opened this issue Nov 4, 2018 · 22 comments
Labels
bug Something isn't working

Comments

@modelica-trac-importer
Copy link
Collaborator

Reported by sjoelund.se on 2 May 2013 15:04 UTC
We should specify which C version external functions use in external "C". Which Fortran version is used is clearly defined, but "C" is just... What is it, really?
Maybe we should also add external "C99" and external "C11" for those of us who like to program with VLAs (if external "C" does not imply these features). Or those of us who just like to use // for line comments...


Migrated-From: https://trac.modelica.org/Modelica/ticket/1088

@modelica-trac-importer
Copy link
Collaborator Author

Comment by Dag Brück on 2 May 2013 15:20 UTC
Just curious: what would this do for you? What do you want to accomplish that you cannot do today? You do not propose changing the Modelica interface to use newer features in C, such as variable length arrays, do you?

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 2 May 2013 15:27 UTC
People use #include "myfile.c" or raw C-code a lot in Modelica libraries, and the different C-versions are not fully compatible with each other. If you compile using C89, //-style comments are illegal. If you compile using C++, some type conversions, and all implicit functions are illegal. And so on.

The language standard does matter, if only a little. If you force the tool to use a specific language version, if you have different libraries that depend on different language features, you are in trouble.

The main benefit is users would actually target a single C version and know their code worked.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by jmattsson on 2 May 2013 15:49 UTC
I'd prefer specifying a single standard for the includes, preferably C89. Allowing different standards would among other things lead to problems if someone would need to use two libraries that uses different C standards for their externals.

Also, you shouldn't use #include "myfile.c", it is just asking for trouble. I think the example in the spec that uses that should be removed. I know there are legitimate reasons to do it, but it is usually done out of ignorance or laziness. Also, if you are, say, compiling for an embedded system and want the improved optimization that you might get from such a trick, then you'd probably want to use C89 anyway.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 2 May 2013 16:41 UTC
Well... Include="#include \"myfile.c\"" (or Include="void f ...") is very, very convenient. It ensures that most Modelica tools can load the library and everything would just work. No libraries that need to be compiled and linked. Of course, having pre-compiled libraries is faster especially if the code is large.

But for many models, it is a reasonable trade-off considering it is not specified how a tool should compile (and which annotations should be used) for C-sources compiled into libraries.

That said, I too dislike that we use Include=#include "myfile.c"; Library="myfile.c" would be nicer.

Of course, I also think we should have just allowed inline C in the first place, so I am probably crazy:

function f
  input Real i;
  output Real o;
protected
  Real arr[4];
external "C" /* in the header, so global stuff */
  #include <math.h>
algorithm
  arr := fill(1,4);
external "C" /* in the algorithm section, so access local variables directly in the code for some C subset */
  if (i<0.5) {
    o = cos(sin(arr[2]));
  } else {
    o = 0.0;
  }
end external;
  o := arr[3] + o;
end f;

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 2 May 2013 17:06 UTC
The external-line to me indicates how to call the function (linkage and how to pass parameters) and nothing more.

That is normally the same regardless of C-language version - and the code could be written in any language as long the code can be called as though it was C-code.

For included code it makes sense to go for the common stable ground, i.e. C89.
It might possibly be C11 excluding optional parts in the future (assuming that C11 does not go the way of C99), that would allow // comments but not VLAs.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by sjoelund.se on 2 May 2013 17:12 UTC
Actually, in C11, there is a feature-test macro __STDC_NO_VLA__. So you can write code that supports VLAs even if you do not require that the compiler implemented it.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by thiele on 6 May 2013 07:15 UTC
Replying to [comment:4 sjoelund.se]:

Having worked at libraries that extensively use external C code it turned out that (despite some disadvantages) the most robust way of interfacing to C was to just use the Include="#include \"myfile.c\"" style. We had an extreme case there using static libraries even lead to incompatibilities between installation using the same MS VS compiler version that just differed in their patch level.

However, I also don't like to have to "misuse" the Include="#include \"myfile.c\"" for that purpose. I like the proposed inline mixing style, though it would need to be considered whether the added complexity to the Modelica language is worth their introduction.

What would be more //urgently// needed in my opinion is a mechanism to give a more fine grained control over a build process involving external C code. E.g., s.th. like this: Sources={"file1.c", "file2.cpp"}, CFlags="-O2", CPPFlags="-O1", etc..

Of course, complete control of a C/C++ build process (especially if several platforms shall be supported) is arbitrarily extensive, therefore one would need to find a design compromise which should cover the most common use-cases.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 23 Sep 2013 16:50 UTC
Language group: The C-code should be valid C89 - but delay until next revision.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 31 Mar 2016 12:28 UTC
Replying to [comment:8 hansolsson]:

Language group: The C-code should be valid C89 - but delay until next revision.

Corrected in r9239.
Note that a better system for distributing libraries relying on external code would be good - but that goes beyond this ticket.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by m.thorade on 15 Nov 2016 10:05 UTC
Sorry for answering late on an already closed ticket:
Support for some interesting mathematical functions was added in C99:
https://en.wikipedia.org/wiki/C_mathematical_functions
Visual Studio improved C99 support with VS2013 and now comes with a much nicer math.h

One example function that was added in C99 is erf,
the following works just fine (tested in Dymola on Windows, as well as OpenModelica on Xubuntu):

function erf "error function"
  extends Modelica.Icons.Function;
  input Real u;
  output Real y;
external"C" y = erf(u);
end erf;

Is this code illegal? According to MLS_3.3? According to MLS_3.4?
Thanks for clarification.

Related: thorade/ExtraMath#4

@modelica-trac-importer
Copy link
Collaborator Author

Comment by beutlich on 15 Nov 2016 10:10 UTC
We already have external "FORTRAN 77", so why can't we add the external "C 89" and external "C 99" C standards to specifically allow C99 functions and to have it consistent with FORTRAN?

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 15 Nov 2016 11:01 UTC
Replying to [comment:11 beutlich]:

We already have external "FORTRAN 77", so why can't we add the external "C 89" and external "C 99" C standards to specifically allow C99 functions and to have it consistent with FORTRAN?

We could, although I think the names are normally C89, C99 and C11 (without spaces) - even though formally we now only have "ISO/IEC 9899:2011" as C11.
http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=57853

The problem is how to use this information:

  • C11 doesn't seem to add new major mandatory library-parts - and even C99-parts become optional. Thus C11 and C99 can likely be treated the same.
  • VS 2013 supports part of C99, and VS 2015 supports almost all parts of C99 - but we could hope that VS 2013 is enough.
  • C11 is not strictly backwards compatible - gets was removed (hurray!), we can hope it isn't used.
  • The simple solution would be to detect that C99 or C11 is used then generate diagnostic if the selected compiler doesn't support that; through the GUI and/or ifdef-code.

The implication is thus that we should state that C99/C11 should only be used when necessary; which means that C11 is practically never necessary.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by beutlich on 15 Nov 2016 11:59 UTC

The simple solution would be to detect that C99 or C11 is used then generate diagnostic if the selected compiler doesn't support that; through the GUI and/or ifdef-code.

I prefer that simple solution. It is similar to what I proposed in thorade/ExtraMath#3.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by beutlich on 4 Jan 2017 14:13 UTC
See #2145 for improved support of building external functions from sources.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by dag on 9 Jan 2017 09:20 UTC
I do not think we should push this too far. After all, we want to promote Modelica not C. The current resolution is good enough. Two observations:

  1. The Modelica tool may not know which which C compiler will be used or what level of C is supported, for example if the tool supports multiple compilers or is used to export code to another platform.

  2. It is possible to test the level of C in the C code and use alternate code or issue appropriate error messages using #error. For most cases the C code would be portable between C89, C99 and C11; for special cases you can manage the compatibility checks in the C code.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by beutlich on 9 Jan 2017 10:01 UTC
Replying to [comment:15 dag]:

I do not think we should push this too far. After all, we want to promote Modelica not C.

Sure. But nevertheless the interface should be clearly defined.

The current resolution is good enough.

To me, it looks like https://github.com/thorade/ExtraMath (which explicitly uses C99 features) is legal according to MLS 3.3 but no longer accroding to MLS 3.4. I want to avoid this and say that C89 is recommended. So tools should not add -std=C89 as compiler flag.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by dag on 9 Jan 2017 10:16 UTC
Replying to [comment:16 beutlich]:

To me, it looks like https://github.com/thorade/ExtraMath (which explicitly uses C99 features) is legal according to MLS 3.3 but no longer accroding to MLS 3.4. I want to avoid this and say that C89 is recommended. So tools should not add -std=C89 as compiler flag.

Agreed. Maybe "C89 or later", we need not support any earlier version.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by volker.beuter on 10 Jan 2017 09:36 UTC
Replying to [comment:17 dag]:

Replying to [comment:16 beutlich]:

To me, it looks like https://github.com/thorade/ExtraMath (which explicitly uses C99 features) is legal according to MLS 3.3 but no longer accroding to MLS 3.4. I want to avoid this and say that C89 is recommended. So tools should not add -std=C89 as compiler flag.

Agreed. Maybe "C89 or later", we need not support any earlier version.

If I understand this discussion correctly the argument is that C99 has additional features we may not want so support from Modelica. So "C89 or later" won't help. If the
used compiler only supports C89 it fails, if it (also) supports C99 the same source runs. And this effect ought to be avoided, right?

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 28 Feb 2017 17:42 UTC
Should be possible to state C-version using "C89", "C99", "C11" (and later releases), and the tool will use that information.
Favor: 4
Against: 0
Rest abstain.

Seems clear - but will need to consider exactly how.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by dag on 1 Mar 2017 08:26 UTC
There is of course no guarantee that the target environment supports a particular version of C, or allows you to choose between different versions. The question is also what you do if one function specifies "C89" and another "C11".

If we want to go into this level of detail, wouldn't it then make sense to be able to specify which compiler you need? People often write code that only works on a particular compiler, e.g. gcc.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by beutlich on 1 Mar 2017 13:02 UTC

If we want to go into this level of detail, wouldn't it then make sense to be able to specify which compiler you need?

At least the corresponding library can be set in a compiler-specific way (since #1316 is resolved for Modelica 3.4). Thus the linking should be less error-prone.

@modelica-trac-importer
Copy link
Collaborator Author

Comment by hansolsson on 14 Mar 2017 15:10 UTC
Added possibility for this - and specified that it is intended for linking and generating diagnostics, r9685.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment