LNK2005 Error in Windows Form CLR

I am working on creating a Windows CLR form to create GUI interactions for some code that I processed as a console program.

When I include a header in the console part of the code, both of my headers work fine together, but when I try to include them in the form, they lead to the following:

librarytest.obj: LNK2005 error: _SeqWait is already defined in Gesture_Elicitor.obj

librarytest.obj: error LNK2005: _KillDLL already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _SetSinFreq2 already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _ConnectDirect already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _GetDevice already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _SetSinFreq_Fine2 already defined in Gesture_Elicitor.obj

librarytest.obj: error LNK2005: _Connection is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _TacOnTimeForTAction already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _SetSinFreq1 is already defined in Gesture_Elicitor.obj

librarytest.obj: error LNK2005: _GetLastEAIError is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _SetGain is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _Disconnect is already defined in Gesture_Elicitor.obj

librarytest.obj: error LNK2005: _ReadFWVer is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _SetSinFreq_Fine1 already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _SetSigSrc already defined in Gesture_Elicitor.obj

librarytest.obj: error LNK2005: _ClosePort is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _ShowDebugInfo is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _OpenPort is already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _DiscoverDevices already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _TacOnTime already defined in Gesture_Elicitor.obj

librarytest.obj: LNK2005 error: _PulseOnTime already defined in Gesture_Elicitor.obj

librarytest.obj: error LNK2005: _tactorhandle is already defined in Gesture_Elicitor.obj

....

An interesting problem is that one of my headers ("wiimote.h", from the WiiYourself project) works fine if only one is included in it. The problem is "tactor_cHeader.h", which connects to its .dll. The abbreviated code in question is as follows:

#ifndef TACTOR_H_ #define TACTOR_H_ using namespace std; #include <windows.h> ... typedef int (*ConnectDirectPtr)(char*name, int type); typedef int (*TacOnTimePtr)(int cidx, int board, int tacNum, int durMilli, bool returnifprocessing); typedef int (*SetFreqPtr)(int cidx, int board, int freq, bool returnifprocessing); typedef int (*KillDLLptr)(); typedef int (*SeqWaitPtr)(int cidx, int board, int waitTime, bool returnifprocessing); ... ConnectDirectPtr ConnectDirect; TacOnTimePtr TacOnTimeForTaction; SetFreqPtr SetSinFreq1; SetFreqPtr SetSinFreq2; KillDLLptr KillDLL; SeqWaitPtr SeqWait; ... HINSTANCE tactorhandle = NULL; inline int InitTactorDLL() { tactorhandle = LoadLibrary("Tactor_DLL.dll"); if (tactorhandle == 0) return -1; SeqWait = (SeqWaitPtr)GetProcAddress(tactorhandle, "SeqWait"); ConnectDirect = (ConnectDirectPtr)GetProcAddress(tactorhandle, "ConnectDirect"); TacOnTime = (TacOnTimePtr)GetProcAddress(tactorhandle, "TacOnTime"); SetSinFreq1 = (SetFreqPtr)GetProcAddress(tactorhandle, "SetSinFreq1"); SetSinFreq2 = (SetFreqPtr)GetProcAddress(tactorhandle, "SetSinFreq2"); KillDLL = (KillDLLptr)GetProcAddress(tactorhandle, "KillDLL"); } #endif 

So what is this heading that doesn't play well with my form?

+1
source share
1 answer

Sorry for the late reply.

The problem is simple, you have definition variables inside your header file. Typically, the header file should only contain declarations declarations . Note [SO]: what is the difference between definition and declaration? to see the difference between the two.

To fix , you have to move this:

 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 three steps when creating C (C ++) code in Portable Executable code (here I mean .exe and .dll files). For more information, check out [MS.Docs]: peering inside PE: Win32 executable file format overview :

  1. Preprocess

    • Made by a preprocessor (cl.exe: [MS.Docs]: Compiler options are listed in alphabetical order ), which is also a compiler (see next step); by default, this is a silent phase (you can see its output by specifying the / E, / EP or / P flags)
    • For each source file (.c, .cpp, .cxx, C ++, ...) it processes all preprocessing directives ( [MS.Docs]: preprocessor directives ) (for example: #define, #if, #include, .. .); The result is a .c file (.cpp, ...) (different from the original, usually much larger), also called a compilation or translation module
    • .When the #include directive is encountered, the line containing the directive (there is only one file included in the line of code) is simply replaced by the contents of the file (.h or even .c (.cpp, ...)) is included. Please note that this is done recursively (if the included file itself contains the #include directives, they also expand, etc.). The original source file is much smaller than the pre-processed one, which is one of the reasons for the existence of the preprocessor.
  2. Compilation

    • Made by the compiler (check the previous step)
    • Each translation unit generated in the previous step is converted from C (C ++) code (human readable) to machine code ("readable CPU") or to COFF format ( [MS.Docs]: PE format ). This is an object file (.obj) (its contents are nonsense, at least 1 st ), which can be seen in the intermediate directory of the VC project
    • Please note that for each source file included in the project, after this step there will be a corresponding .obj file
  3. .Link

    • Run by the linker (link.exe: [MS.Docs]: linker options )
    • All object files of the previous stage are combined together (with a bunch of .lib files, the contents of which are similar to the .obj file, but they can be used only indirectly - when creating the app application), as well as some additional operations (for example, adding sections and PE headers, moving some code, deleting unused code, ...) into the final project artifact (exe or dll)

Note : it depends on Win, for Nix the phases are (almost) the same, the tools are different.

What happens in your code:

  • The tactor.h file (I assume that its name is based on enabling protection at the beginning) contains many variable definitions; I take HINSTANCE tactorhandle as an example
  • Librarytest.c and Gesture_Elicitor.c files (their names were obtained due to a linker error) and Tract.h #include (directly or indirectly)
  • In step 1 of Phase 1 , Tractor.h will be expanded in both .c files (independently). Thus, both translation units will have a tactor variable
  • At stage 2, 2 translation units from the previous stage are compiled and converted into object files, since their code is syntactically correct
  • In step 3, when combining two object files, the linker sees that both of them have a tactor handle, and then spits out the errors above

.Notes :

  • You can also specify the / FORCE: MULTIPLE option for the linker (adding it to the VC Project Properties β†’ Linker β†’ Command Prompt β†’ Advanced Options), but keep in mind that this may lead to unexpected results (it doesn’t even work for compiled projects / clr )
  • Since the project includes import / export of DLL files and functions, you can also check [SO]: Linker error when calling function C from C ++ code in another VS2010 project (@CristiFati answer) for errors. that may appear when using this .dll
+1
source

All Articles