LNK2005 Error in CLR Windows Form

Sorry for the late reply.

The problem is simple, you have variable definitions inside your header file. Generally, a header file should only contain declarations. Check [SO]: What is the difference between a definition and a declaration? to see the difference between the two.

To fix, you should move these:

ConnectDirectPtr ConnectDirect;
TacOnTimePtr TacOnTimeForTaction;
SetFreqPtr SetSinFreq1;
SetFreqPtr SetSinFreq2;
KillDLLptr KillDLL;
SeqWaitPtr SeqWait;
//...

HINSTANCE tactorhandle = NULL;

into the .c source file that really needs them, or make them extern ([MS.Docs]: extern (C++)).

Backgorund:

There are 3 phases when building C (C++) code into Portable Executable code (here I’m referring to .exe and .dll files). For more info, check [MS.Docs]: Peering Inside the PE: A Tour of the Win32 Portable Executable File Format:

  1. Preprocess

    • Done by the preprocessor (cl.exe: [MS.Docs]:
      Compiler Options Listed Alphabetically
      ) which is also the compiler (check next phase); this is by default a silent phase (you can see its output by specifying /E, /EP or /P flags)
    • For every source (.c, .cpp, .cxx, c++, …) file, it handles all the preprocessing directives ([MS.Docs]: Preprocessor Directives) (e.g.: #define, #if, #include, …); the result is still a .c (.cpp, …) file (different than the original, usually, significantly larger) also called compilation or translation unit
    • When an #include directive is encountered, the line that contains the directive (there’s only one file included per line of code) is simply replaced by the contents of the (.h or even .c (.cpp, …)) file included. Note that this is done recursively (if the file included itself contains #include directives they are expanded as well, and so on). The original source file is much smaller than the preprocessed one, which is one of the preprocessor existence reasons
  2. Compile

    • Done by the compiler (check previous phase)
    • Every translation unit generated at previous phase is converted from C (C++) code (human readable) to machine code (CPU “readable”) or COFF format ([MS.Docs]: PE Format). This is the object (.obj) file (its content is gibberish – at least at 1st sight), that can be seen in the VC project’s intermediary directory
    • Note that for each source file included in the project, after this phase there will be a corresponding .obj file
  3. Link

    • Done by the linker (link.exe: [MS.Docs]: Linker Options)
    • All the object files from the previous phase are merged together (with a bunch of .lib files whose content is similar to .obj file’s, but those can only be used indirectly – when building an app) plus some additional operations (e.g. adding the PE sections and headers, relocating some of the code, removing unused code, …) into the final artifact of the project (the exe or the dll)

Note: this is Win specific, for Nix the phases are (almost) the same, tools differ.

What happens in your code:

  • The file tactor.h (I’m assuming this is its name, based on the include guard at the beginning) contains a bunch of variable definitions; I’m taking HINSTANCE tactorhandle as an example
  • Files librarytest.c and Gesture_Elicitor.c (got their names from the linker error) both #include (directly or indirectly) tractor.h
  • At Phase 1, tractor.h will be expanded in both the .c files (independently). So, both translation units will have tactorhandle variable
  • At Phase 2, the 2 translation units from previous step are compiled and turned into object files, since their code is syntactically correct
  • At Phase 3, when combining the 2 object files, the linker sees that tactorhandle is present in both of them, and then spits the errors above

Notes:

Leave a Comment