I keep getting a group of errors when I run my code as follows:
LNK 2001 unresolved external symbol IID_IMediaEvent
LNK 2001 unresolved external symbol IID_IMediaControl
LNK 2001 unresolved external symbol IID_IGraphBuilder
LNK 2001 unresolved external symbol CLSID_FilterGraph
My code is here:
#include <dshow.h>
#include <stdio.h>
#include <Windows.h>
void main(void)
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("FAIL");
}
else
{
printf("PASS");
}
IGraphBuilder *pGraph=NULL;
hr=CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,&IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr))
{
printf("ERROR - Could not create the Filter Graph Manager.");
return;
}
IMediaControl *pControl=NULL;
IMediaEvent *pEvent=NULL;
hr = pGraph->lpVtbl->QueryInterface(pGraph,&IID_IMediaControl, (void**)&pControl);
hr = pGraph->lpVtbl->QueryInterface(pGraph,&IID_IMediaEvent, (void**)&pEvent);
hr = pGraph->lpVtbl->RenderFile(pGraph,L"C:/Users/User/Desktop/AudioPlayer/trn.wav", NULL);
hr = pControl->lpVtbl->Run(pControl);
long evCode = 0;
pEvent->lpVtbl->WaitForCompletion(pEvent,INFINITE, &evCode);
pControl->lpVtbl->Release(pControl);
pEvent->lpVtbl->Release(pEvent);
pGraph->lpVtbl->Release(pGraph);
CoUninitialize();
}
I have been searching for around two weeks trying to find an answer, but to no help. I think its something to do with linkers, but I have no idea on what I'm doing wrong because I'm fairly new to C and Visual Studio.
The core issue here is that the interface (IID) and class (CLSID) IDs are declared, but not defined. The compiler happily proceeds, delegating the ID lookup to the linker. Since the IDs aren't defined nor exported by any of the supplied import libraries, the linker gives up with an LNK2001 error.
To resolve the issue there are two options: Either have the header files also define the IDs, or pass the import library (strmiids.lib) that exports them to the linker.
The first option has the advantage of working with any compiler. It requires an #include <initguid.h> directive ahead of including any header file that would otherwise merely declare the IDs. <initguid.h> does two things: It defines the INITGUID preprocessor symbol, and subsequently includes <guiddef.h>. It is the latter that changes the preprocessor symbols to define the respective IDs, properly marked as __declspec(selectany) to prevent multiply-defined symbol linker errors.
#include <initguid.h>
#include <dshow.h>
#include <stdio.h>
#include <Windows.h>
...
This should resolve all linker errors.
The other option is to pass the import library strmiids.lib to the linker. This can be done in source code using a #pragma comment(lib, "strmiids") directive, or by passing the import library on the linker command line.
The downside of this is that it needs to be toolchain-specific: Only MSVC and Clang support #pragma comment(lib, ...), and Clang and GCC use different naming for import libraries (libfoo vs. foo.lib). Unless you have a specific reason to use the import library you should go with the first option.
Aside: Since #include <initguid.h> works for any scenario, why do we have options? And why do we need the <initguid.h> toggle at all?
This is probably down to historic events, from a time before the __declspec(selectany) modifier was introduced (Visual Studio 2012). Prior to that, every symbol could be defined at most once. If more than one compilation unit defined the same symbol, the linker would generate a LNK2005, and ultimately fail to produce an artifact.
In those times, client code would generally have a single (usually otherwise empty) compilation unit that had an #include <initguid.h> directive, followed by other headers that declared (and defined) the IDs. The remaining compilation units merely included the header files to declare the IDs, without the <initguid.h> toggle.
After the __declspec(selectany) modifier was introduced, symbols (such as the IDs) could be defined any number of times, so long as the definitions are identical (which the SDK ensures). So today, you can simply #include <initguid.h> in every compilation unit, and things work just fine.
At least that's my interpretation of history derived from a look into the <guiddef.h> file of the Windows SDK.
Related
I am just a beginner in C and Visual Studio and I have this weird error.
I declared a function in cipher.h and defined it in cipher.c (I have included cipher.h in cipher.c). I include cipher.h in main.c and used the function. But it gives me this error while compiling main.c:
unresolved external symbol test_encrypt referenced in function _main
Here are the codes:
cipher.h:
#pragma once
#include <stdio.h>
#include <stdbool.h>
void test_encrypt(char message[]);
cipher.c:
#include "cipher.h"
void test_encrypt(char message[])
{
message[0] = '0';
}
main.c:
#include <stdio.h>
#include "cipher.h"
int main(void)
{
// open a text file and read the text into an array called buffer
// the text is "54321"
test_encrypt(buffer);
printf(buffer);
}
Everything works fine if I remove the line that use test_encrypt function.
Thanks in advance.
Think about the C compilation stages.
First C sources are built into objects. Those are compiled files which are like building blocks of your final executable. When you call cipher in your main, the compiler looks at the included headers and see if it finds anything that matches it. Since you have defined the function prototype, the compiler knows that such function exists somewhere, but it does not know where, at this stage.
The main.o object will have a reference to cipher declared as "external". After this stage of compilation, it's the linker job to be sure that the symbols you have are somewhere. From here it looks either in the other object files or in some libraries, and if it can't find it anywhere, it throws the error you are seeing.
What I can imagine it's happening here is that you didn't specify "cipher.c" to be part of you VS project, hence "cipher.o" is not being built, resulting in the error from the linker.
I'm working on a project which requires to develop the firmware for several esp32. All the microcontrollers share a common code that takes care of wifi and mqtt, however they all have a different behavior, which is defined in a specific component. The structure of my project is something like this:
- CMakeLists.txt
- Makefile
- sdkconfig
- main
- CMakeLists.txt
- main.c
- components
- wifi_fsm
- wifi_fsm.h
- wifi_fsm.c
- CMakeLists.txt
- mqtt_fsm
- mqtt_fsm.h
- mqtt_fsm.c
- CMakeLists.txt
- entity_1
- entity_1.h
- entity_1.c
- CMakeLists.txt
- entity2
- entity2.h
- entity2.c
- CMakeLists.txt
...
Each entity defines some functions with standard names, which implement specific logic for the entity itself and which are called within the shared code (main, wifi_fsm, mqtt_fsm).
void init_entity(); // called in main.c
void http_get(char *buf); // called in wifi_fsm
void http_put(char *buf);
void mqtt_msg_read(char *buf); // called in mqtt_fsm
void mqtt_msg_write(char *buf);
My idea was to have a conditional statement to include at will a specific behavior, so that depending on the entity included, the compiler would link the calls to the functions above to those found in the specific included library. Therefore, at the beginning of main.c I just added the following lines with the goal of having to change the only defined pre-processor symbol to compile for different enity behaviors.
#define ENTITY_1
#ifdef ENTITY_1
#include "entity_1.h"
#elif defined ENTITY_2
#include "entity_2.h"
#elif ...
#endif
#include "wifi_fsm.h"
#include "mqtt_fsm.h"
void app_main(void)
{
while(1){
...
}
}
On the one hand the compiler apparently works fine, giving successful compilation without errors or warnings, meaning that the include chain works correctlty otherwise a duplicate name error for the standard functions would be thrown. On the other hand, it always links against the first entity in alphabetical order, executing for instance the code included in the init_entity() of the component entity_1. If I rename the standard functions in entity_1, then it links against entity_2.
I can potentially use pointers to standard calls to be linked to specific functions in each entity if the approach above is wrong, but I would like to understand first what is wrong in my approach.
EDIT in response to Bodo's request (content of the CMakeFile.txt)
Project:
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(proj)
Main:
set(COMPONENT_REQUIRES )
set(COMPONENT_PRIV_REQUIRES )
set(COMPONENT_SRCS "main.c")
set(COMPONENT_ADD_INCLUDEDIRS "")
register_component()
Component:
set(COMPONENT_SRCDIRS "src")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES log freertos driver nvs_flash esp_http_server mqtt)
register_component()
This answer is based on guessing because I don't have enough information. For the same reason it is incomplete in some parts or may not fully match the use case of the question.
The details about how the project will be built seems to be hidden in a cmake include file like project.cmake or nested include files.
My guess is that the build system creates libraries from the source code of every individual component and then links the main object file with the libraries. In this case, the linker will find a symbol like init_entity in the first library that fulfills the dependency. This means the library (=component) listed first in the linker command line will be used.
If the linker command line would explicitly list the object files entity_1.o and entity_2.o, I would expect an error message about a duplicate symbol init_entity.
I can propose two ways to solve the problem:
Make sure only the selected entity is used to build the program.
Make the identifier names unique in all entities and use preprocessor macros to choose the right one depending on the selected entity.
For the first approach you can use conditionals in CMakeLists.txt. See https://stackoverflow.com/a/15212881/10622916 for an example. Maybe the register_component() is responsible for adding the component to the build. In this case you could wrap this in a condition.
BUT modifying the CMakeLists.txt might be wrong if the files are generated automatically.
For the second approach you should rename the identifiers in the entities to make them unique. The corresponding header files can define a macro to replace the common name intended for the identifier with the specific identifier of the selected entity.
In the code that uses the selected entity you will always use the common name, not the individual names.
Example:
entity_1.c:
#include "entity_1.h"
void init_entity_1(void)
{
}
entity_2.c:
#include "entity_2.h"
void init_entity_2(void)
{
}
entity_1.h:
void init_entity_1(void);
// This replaces the token/identifier "init_entity" with "init_entity_1" in subsequent source lines
#define init_entity init_entity_1
// or depending on the parameter list something like
// #define init_entity() init_entity_1()
// #define init_entity(x,y,z) init_entity_1(y,x,z)
entity_2.h:
void init_entity_2(void);
#define init_entity init_entity_2
main.c
#define ENTITY_1
#ifdef ENTITY_1
#include "entity_1.h"
#elif defined ENTITY_2
#include "entity_2.h"
#elif ...
#endif
void some_function(void)
{
init_entity();
}
In this example case with #define ENTITY_1, the preprocessor will change some_function to
void some_function(void)
{
init_entity_1();
}
before the compilation step and the linker will use init_entity_1 from entity_1.c. An optimizing linker may then omit the object file entity_2.o or the corresponding library because it is unused.
I currently build a purely static library MainLib for our customers that contains all symbols so that they can intrgrate it into their program. For several reasons, I now need to deliver a DLL version of MainLib that contains parts of the symbols alongside a static library FeatureLib that contains the remaining symbols. One reason is that we want to avoid bad guys using our software by simply stealing the DLL that is provided via the program of our customer. This wouldn't work if parts of the symbols are integrated within the calling software via a static library. The user of the package shall only be able to use the DLL if he added the symbols of FeatureLib into his application.
For Linux, I can make this work like a charm,i.e. the symbol doFeature() is not within libMainLib.so, but I don't succeed on this for Windows.
CMakeLists.txt:
cmake_minimum_required(VERSION 3.0)
project(MainLib)
add_library(FeatureLib STATIC src/FeatureLib.c)
target_include_directories(FeatureLib PUBLIC include
PRIVATE src)
add_library(MainLib SHARED src/MainLib.c)
target_include_directories(MainLib PUBLIC include
PRIVATE src)
# I don't want to include symbols from FeatureLib into shared MainLib
#target_link_libraries(MainLib PRIVATE FeatureLib)
add_executable(MainLibDemo src/demo.c)
target_link_libraries(MainLibDemo MainLib FeatureLib) #resolve symbol doFeature()
FeatureLib.h:
extern int doFeature(int input);
MainLib.h:
extern __declspec(dllexport) int MainLib(int input);
FeatureLib.c:
#include "FeatureLib.h"
int doFeature(int input) {return 4;}
MainLib.c:
#include "FeatureLib.h"
#include "MainLib.h"
__declspec(dllexport) int MainLib(int input)
{
if (input > 2) {
return doFeature(input);
} else {
return doFeature(0);
}
}
demo.c:
#include <stdio.h>
#include <stdlib.h>
#include "MainLib.h"
int main(int argc, char **argv)
{
if(argc > 1)
return MainLib(atoi(argv[1]));
else
return 0;
}
With this, I get the following compilation error:
"C:\Daten\tmp\DemoProject\simple\build\ALL_BUILD.vcxproj" (Standardziel) (1) ->
"C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj" (Standardziel) (4) ->
(Link Ziel) ->
MainLib.obj : error LNK2019: unresolved external symbol _doFeature referenced in function _MainLib [C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj]
C:\Daten\tmp\DemoProject\simple\build\Debug\MainLib.dll : fatal error LNK1120: 1 unresolved externals [C:\Daten\tmp\DemoProject\simple\build\MainLib.vcxproj]
0 Warnung(en)
2 Fehler
Is this even possible with Windows? What do I have to do to make it work and how can I verify it other than not linking FeatureLib to MainLibDemo. Any ideas are very welcome.
Kind regards,
Florian
The way you do it under Linux will not work under Windows
because dynamic linking works differently here.
Here is one strategy that could work.
In MainLib.dll code, instead of directly calling doFeature
you need to define a global pointer variable of proper function
pointer type and use it to call the function.
This will allow to build MainLib.dll without errors.
Now you need to set this pointer variable. One way would be:
Add exported function to MainLib.dll that takes pointers
to all functions that the DLL needs from the executable.
In FeatureLib.lib code add an initialisation function
that the application will need to call before using
your DLL which will pass pointers to its peers to the DLL.
This is basically the way most programs with plugins use to
give the plugins access to their facilities.
Another way would be to (Warning! I have not tested this specific
solution):
Declare the functions in FeatureLib.lib as exported
with __declspec(dllexport). This way they will be exported
from executable.
In MainLib.dll before first using the pointers use
GetModuleHandle and GetProcAddress to obtain the pointers.
It would best be done in some initialisation function for the
library. Otherwise you need to take care to avoid race conditions.
Hope this will help.
Though I do not think your copy protection scheme will work.
Andrew Henle is right in his comment: it is not hard
to extract the needed code from one executable and include it
in another.
I am programming stm8s and sht20 from sensirion company with I2C on the IAR. I'm using sht20 sample code: this link
I edited this sample code to my mcu. Then, for example I included i2c_hal.h to my main.c, but functions not working in my main.c file and IAR error is
ERROR LI005 no defition for I2c_Init()
Linking error
For example:
main.c
#include "stm8s.h"
#include "i2c_hal.h"
I2c_Init();
i2c_hal.h
#ifndef I2C_HAL_H
#define I2C_HAL_H
void I2c_Init ();
#endif
i2c_hal.c
#include "I2C_HAL.h"
void I2c_Init ()
{
SDA=LOW;
SCL=LOW;
SDA_CONF=LOW;
SCL_CONF=LOW;
SDA=HIGH;
SCL=HIGH;
}
I copied sht20 files to my project directory. What should I do for this error?
The header file is read by the preprocessor not the linker; if you get as far as linking, it is not a header file issue. The three basic build steps for C code are:
preprocess
compile
link
Your build is failing at the link state. The linker requires all compiled object files and any necessary libraries that constitute your application as input. In your case the most likely issue is that you have not compiled and linked i2c_hal.c (or strictly compiled i2c_hal.c and linked i2c_hal.obj). In the IAR IDE you simply explicitly add i2c_hal.c to your project along with main.c, and all should be good (all other dependencies being satisfied).
I suspect that i2c_hal.c will infact fail compilation since it is missing any declaration of SDA, SCL etc. - you probably need to include stm8s.h there also.
In general the process looks like this (this diagram actually omits pre-processing - i.e. expansion of headers, macros and conditional compilation etc. - but it was the otherwise clearest example I found; the original page does however mention the pre-processor stage, and the preprocessor is normally run automatically when you invoke the compiler in any case):
I have also the same issue with the spi. I got hal_spi_init() linking problem. To resolve the issue you need to enable the I2C in your stm32 hal drivers. In stm32xx_hal_conf.h file we have different #define modules. There you can enable the I2C module or just include the defined symbol in your IAR tool. Then Issue resolved
You need to add the C source files to the project. Header files shall not have any code or data, only the declarations of types , extern variables, macros, static inline functions and function prototypes.
I have been having these really odd problems with Visual Studio 2010. At this point, the behavior is so erratic that I really wish I did not have to use it for CUDA (I know I don't have to, but it is hard not to use it).
One of the many problems I have been having with really basic stuff is header files being included more than once. For example:
//vars.cuh
#if !defined(VARS_cuh)
#define VARS_cuh
#include <cuda.h>
#include <cuda_runtime_api.h>
int* kern_xstart, *kern_xend, *kern_ystart, *kern_yend, *kern_zstart, *kern_zend;
/* more variable definitions */
#endif
I then include this file in most of my source files:
//source_file.cu
extern "C"{
#include "vars.cuh"
/* more includes of my own headers */
#include <cuda.h>
#include <cuda_runtime_api.h>
}
/* source file body */
The VS 2010 compiler puts out errors like this: "error LNK2005: foo already defined in other_source_file_I_wrote.cu.obj"
Why is it doing this? Also, to kill two birds with one stone, with this setup, I also have problems with writing a function in source_file.cu, and then prototyping it in vars.cuh. The problem arrises that vars.cuh can't see the definition, even though I am clearly including vars.cuh in source_file.cu!
Thank you!
The header file is being compiled multiple times because, as you say, you include this header file in most of your source files. Those global variables are included in multiple source files and thus are defined in every source file that includes the header. When the linker links all of the object files together, it finds multiple definitions of those variables, hence the error.
If you want to share global variables across multiple source files, declare them as extern in the header, then define each of them once in one source file.
This isn't a problem with Visual Studio or the Visual C++ compiler, it's how C works.