• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

MSFS20 WASM Question - Is WASM ignoring preprocessor command in some cases?

Messages
1,040
Country
ca-ontario
Hi Everyone! Is there an area in the forum to post MSFS2020 WASM C++ development questions? I couldn't find one, so I am posting here, as it is still SimConnect related.

I have a few variables in my header file “module.h”, like this:
Code:
#ifndef __MODULE__H
#define __MODULE__H

bool WPSent;
enum INPUT_ID {
    INPUT_ZX,
};
...
#endif
However, the compiler keeps giving me “duplicate symbol” error on WPSent:
Code:
wasm-ld : error : duplicate symbol: WPSent
and is fine with the enum. I also tried
Code:
#pragma once
but that produces the same error. Is WASM ignoring preprocessor commands for certain variables or am I missing something? For now, I am resorting to using externs in my source files, but that is really annoying. Any thoughts on how to address this?
 
Hi Misho,

This isn't WASM specific but a general C/C++ issue. There are better explanations of this online, but essentially the include guard isn't going to help here because each unit (.c[pp]) which #includes the header still gets its own copy of `WPSent`, which leads to the duplicate symbol errors.

You can keep using externs, there's nothing really wrong with that besides possibly style preference.

You could declare your shared vars as static in the header.

You could create a struct/class to contain your shared vars. The actual definition instance (holding the shared values) would still need to be defined in a .c[pp] file. But you could declare the struct in module.h as extern (and define it in eg. module.cpp) so at least there's only one extern to worry about instead of multiple vars.

HTH,
-Max
 
Last edited:
I'd typically caution about using complex (non-POD) shared static types due to possible initialization issues (eg search "static initialization order fiasco") but I don't really see a way for that to be an issue in the WASM environment (famous last words?).

Anyway if I had more than one var to share I'd (usually) use an extern struct/class so at least every declaration addition/change is in one place and defaults can be assigned in there as well. I updated my first post to clarify about such a struct/class instance still needing to be defined in only one unit (or probably safe to make a static one in this case).
 
Thanks everyone for their input!

I posted this q in the FS2020 devsupport forum, and I got someone from Asobo respond in a bit of a cryptic way, saying that these compiler guards are used in the "same compilation unit", as in, the same CPP. But that's just it - I thought their purpose was to prevent declaration of the same variable in DIFFERENT .cpp files.

Another source of my confusion was that these compiler guards work when compiled with the standard VS compiler. So, there must be something different between VS compiler and WASM compiler. The code I have is a module I used in P3D, compiled as DLL, and it compiled without any errors, so I was a bit concerned when it produced errors in WASM.

I know how to fix it (I’ll probably go with declaring all vars static, or do away with them altogether) but I was wondering why is WASM “complaining” about this, and the standard VS is not?
 
What you're seeing is actually a linker error. Since WASM uses C style linkage (so the exported names aren't mangled), you get duplicate symbols in the final binary. So I really should have said it's a "C issue," not CPP.

But even with CPP, global non-static vars in a header shouldn't work across compilation units in terms of actually sharing the current value. Each unit would get its own copy.
Eg. first hit from a quick search (although there could be, and probably are, whole books written on the subject): https://stackoverflow.com/questions/19929681/c-global-variable-declaration

As mentioned in that Q/A, modern C++ adds some possible workarounds like inline declarations and probably other tricks... Though as also mentioned there, using globals like that in CPP isn't very OO. And again, in most cases one needs to be careful with global statics in terms of initialization.

Cheers,
-Max
 
I thought [include guard] purpose was to prevent declaration of the same variable in DIFFERENT .cpp files.
No... that wouldn't actually work since the point of a header file is to be used in separate .c[pp] files in the first place. As a central way to declare things, not to define them. If each header was only processed once, then only the "first" unit would get the declarations, and for any following units it would be as if the header file/info didn't even exist.
 
What you're seeing is actually a linker error. Since WASM uses C style linkage (so the exported names aren't mangled), you get duplicate symbols in the final binary. So I really should have said it's a "C issue," not CPP.

But even with CPP, global non-static vars in a header shouldn't work across compilation units in terms of actually sharing the current value. Each unit would get its own copy.
Eg. first hit from a quick search (although there could be, and probably are, whole books written on the subject): https://stackoverflow.com/questions/19929681/c-global-variable-declaration

As mentioned in that Q/A, modern C++ adds some possible workarounds like inline declarations and probably other tricks... Though as also mentioned there, using globals like that in CPP isn't very OO. And again, in most cases one needs to be careful with global statics in terms of initialization.

Cheers,
-Max

Okay - but sometime there are cases that call for a project-wide global, like HANDLE hSimConnect; of which can there only be one, but it needs to be used in multiple .cpp files.. In that case, I define it in my .cpp file:

HANDLE hSimConnect = NULL;

And in my header file declare it as:

extern HANDLE hSimConnect;

and now I can use it in any .cpp file that has that header file included. Is that the safe/proper way of using globals?
 
  • Like
Reactions: tml
Is that the safe/proper way of using globals?

Yes, exactly.

If you look at most any pure C code project with multiple units, they most likely need to share vars/structs, and you will commonly see this extern pattern being used. Same for functions as well (though as a matter of style those could also be "wrapped" inside structs, with only the structs being shared/extern, which is more like C++/OO with classes).

As a random example, because I knew exactly where to look for it... :) This is a "module" from a pure-C firmware for a multirotor "drone" controller ("brain"). In modern C++ terms this would be a "singleton" class, meaning only one of these would exist per application/program.
https://github.com/mpaperno/aq_flight_control/blob/next/src/telemetry.h
 
Hi,

I tried asking ChatGPT (this is GPT 4.0 paid version) about your issue, and the reply was scaringly accurate, explaining the difference between "weak" and "strong" linking for symbols used by the standard VC linker vs the WASM one:

 
This human feels a fondness for algorithms addressing from the first person. 😍 Also, I know where I'm spending my lunch money!
 
Back
Top