I'm pretty new to working with third party stuff and also new to working on Windows with C.
I'm currently trying to simply use and include this third party library.
I've downloaded it and put all the files in include/subhook/ next to my main file.
My main.c looks like the example on the github page, except it includes include/subhook/subhook.h:
#include <stdio.h>
#include "include/subhook/subhook.h"
subhook_t foo_hook;
void foo(int x) {
printf("real foo just got called with %d\n", x);
}
void my_foo(int x) {
subhook_remove(foo_hook);
printf("foo(%d) called\n", x);
foo(x);
subhook_install(foo_hook);
}
int main() {
foo_hook = subhook_new((void *)foo, (void *)my_foo, 0);
subhook_install(foo_hook);
foo(123);
subhook_remove(foo_hook);
subhook_free(foo_hook);
}
and this is my CMakeLists.txt file. I've also tried including all the other .c files but it won't work:
cmake_minimum_required(VERSION 3.7)
project(NexusHookSubhook)
set(CMAKE_C_STANDARD 11)
include_directories(include/subhook)
set(SOURCE_FILES main.c include/subhook/subhook.h include/subhook/subhook.c)
add_executable(NexusHookSubhook ${SOURCE_FILES})
When I try to compile I get a whole load of these errors (which is, I assume, from linking/including the library wrong). Can anyone explain what I'm doing wrong here?
C:\Users\Nakroma\.CLion2017.1\system\cygwin_cmake\bin\cmake.exe --build C:\Users\Nakroma\CLionProjects\NexusHookSubhook\cmake-build-debug --target NexusHookSubhook -- -j 4
[ 33%] Linking C executable NexusHookSubhook.exe
CMakeFiles/NexusHookSubhook.dir/main.c.o: In function `my_foo':
/cygdrive/c/Users/Nakroma/CLionProjects/NexusHookSubhook/main.c:12: undefined reference to `__imp_subhook_remove'
/cygdrive/c/Users/Nakroma/CLionProjects/NexusHookSubhook/main.c:12:(.text+0x3c): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__imp_subhook_remove'
/cygdrive/c/Users/Nakroma/CLionProjects/NexusHookSubhook/main.c:17: undefined reference to `__imp_subhook_install'
/cygdrive/c/Users/Nakroma/CLionProjects/NexusHookSubhook/main.c:17:(.text+0x69): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__imp_subhook_install'
CMakeFiles/NexusHookSubhook.dir/main.c.o: In function `main':
/cygdrive/c/Users/Nakroma/CLionProjects/NexusHookSubhook/main.c:21: undefined reference to `__imp_subhook_new'
....
Additional notes: I'm on Windows 10 with Cygwin 2.8.0 and CMake 3.7.2 (using the make and gcc package and GDB 7.11.1)
you totally miss the linking part in your CMakeFiles
target_link_libraries(
NexusHookSubhook
${subhookLib}
m
)
Where subhookLib is the library of subhook.
I would recommend the following things:
Replace
#include "include/subhook/subhook.h"
with
#include "subhook.h"
as first part of the path is already included over here:
include_directories(include/subhook)
Only include the .c files as SOURCE_FILES:
set(SOURCE_FILES main.c include/subhook/subhook.c)
Related
I have 2 c files (& their header files). I have included the function "put" in the corresponding header, but I still have the following errors, when I input "gcc -o main main.c" in the terminal.
main.c:(.text+0x389): undefined reference to `put' collect2: error: ld
returned 1 exit status
may I know the reason? How should I modify my code?
I tried to change the linking order in makefile but failed. Any advice is appreciated, thanks!
CMakeLists.txt
cmake_minimum_required(VERSION 3.19)
project(Demo)
set(CMAKE_CXX_STANDARD 14)
include_directories(.)
add_executable(Demo
main.c main.h KeyValueStore.c KeyValueStore.h )
main.c
#include "main.h"
...
int main() {
...
if (strcmp("PUT", tokens[0]) == 0) {
put(tokens[1], tokens[2]);
...
}
main.h
...
#include "KeyValueStore.h"
...
KeyValueStore.c
#include "KeyValueStore.h"
#define BUFSIZE 1024
typedef struct KeyValueStore {
char key[BUFSIZE];
char value[BUFSIZE];
} KV_Store;
KV_Store kvStore[BUFSIZE];
...
int put(char* key, char* value){
...
}
KeyValueStore.h
...
typedef struct KeyValueStore;
int put(char* key, char* value);
...
Check to see if you have any .o files in that folder and delete them if you do. It's possible the compiler failed at some point while compiling which left *.o files that aren't linked properly
EDIT: I misread the question because for some reason it came up as a c++17 question for me. I'm not sure if what I said still applies to C though I do know it works with C++. Sorry about that to everyone that read my answer before I edited it
Not 100% sure if this is why you are having the error, though you need to put all .c files in the compiler.
So you currently are trying to "gcc -o main main.c" where instead you want to do something more like "gcc -o main main.c keyValueStore.c".
If you do not give the compiler every .c file, it won't have all the definitions and you will get an error similar to what you have.
I also don't really think you need main.h, assuming there isn't any more code in there, it really isn't worth having a whole extra file and instead just putting the #include in main.c.
I'm trying to compile a sample 64-bit c progam using the ftd2xx lib by FTDI using gcc within cygwin without any success. I always end up in linker errors.
My project contains these file:
main.c My Sample Application
ftd2xx.h The header of the library
ftd2xx.lib Importlibrary
ftd2xx64.dll dynamic library 64 bit
wintypes.h Wrapper used by ftd2xx.h to include windows.h
This is my main function:
#include <stdio.h>
#include <windows.h> // for windows specific keywords in ftd2xx.h
#include "ftd2xx.h" // Header file for ftd2xx.lib
int main()
{
FT_HANDLE ft_handle; // handle to the USB ic
FT_STATUS ft_status; // for status report(error,io status etc)
ft_status = FT_Open(0,&ft_handle); //open a connection
if(ft_status == FT_OK) //error checking
{
printf("\n\n\tConnection with FT 232 successfull\n");
}
else
{
printf("\n\n\tConnection Failed !");
printf("\n\tCheck device connection");
}
FT_Close(ft_handle); //Close the connection
return 0;
}
This is my linker cmd
Building target: testSimple.exe
Invoking: Cygwin C Linker
gcc -L/cygdrive/e/jschubert/workspaces/testSimple/ -o "testSimple.exe" ./main.o -lftd2xx
And here is my output
/cygdrive/e/jschubert/workspaces/testSimple//ftd2xx.lib(FTD2XX.dll.b):(.text+0x2): relocation truncated to fit: R_X86_64_32 against symbol `__imp_FT_Open' defined in .idata$5 section in /cygdrive/e/jschubert/workspaces/testSimple//ftd2xx.lib(FTD2XX.dll.b)
/cygdrive/e/jschubert/workspaces/testSimple//ftd2xx.lib(FTD2XX.dll.b):(.text+0x2): relocation truncated to fit: R_X86_64_32 against symbol `__imp_FT_Close' defined in .idata$5 section in /cygdrive/e/jschubert/workspaces/testSimple//ftd2xx.lib(FTD2XX.dll.b)
After reading the article How does the Import Library work? Details? and http://www.mikrocontroller.net/topic/26484 I'm pretty shure that there is a problem with the generated export lib functions. But how do I correct them?
On Cygwin -mcmodel=medium is already default. Adding -Wl,--image-base -Wl,0x10000000 to GCC linker fixed the error.
I am using dlsym to look up symbols in my program, but it always returns NULL, which I am not expecting. According to the manpage, dlsym may return NULL if there was an error somehow, or if the symbol indeed is NULL. In my case, I am getting an error. I will show you the MCVE I have made this evening.
Here is the contents of instr.c:
#include <stdio.h>
void * testing(int i) {
printf("You called testing(%d)\n", i);
return 0;
}
A very simple thing containing only an unremarkable example function.
Here is the contents of test.c:
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
typedef void * (*dltest)(int);
int main(int argc, char ** argv) {
/* Declare and set a pointer to a function in the executable */
void * handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
dlerror();
dltest fn = dlsym(handle, "testing");
if(fn == NULL) {
printf("%s\n", dlerror());
dlclose(handle);
return 1;
}
dlclose(handle);
return 0;
}
As I step through the code with the debugger, I see the dlopen is returning a handle. According to the manpage, If filename is NULL, then the returned handle is for the main program. So if I link a symbol called testing into the main program, dlsym should find it, right?
Here is the way that I am compiling and linking the program:
all: test
instr.o: instr.c
gcc -ggdb -Wall -c instr.c
test.o: test.c
gcc -ggdb -Wall -c test.c
test: test.o instr.o
gcc -ldl -o test test.o instr.o
clean:
rm -f *.o test
And when I build this program, and then do objdump -t test | grep testing, I see that the symbol testing is indeed there:
08048632 g F .text 00000020 testing
Yet the output of my program is the error:
./test: undefined symbol: testing
I am not sure what I am doing wrong. I would appreciate if someone could shed some light on this problem.
I don't think you can do that, dlsym works on exported symbols. Because you're doing dlsym on NULL (current image), even though the symbols are present in the executable ELF image, they're not exported (since it's not a shared library).
Why not call it directly and let the linker take care of it? There's no point in using dlsym to get symbols from the same image as your dlsym call. If your testing symbol was in a shared library that you either linked against or loaded using dlopen then you would be able to retrieve it.
I believe there's also a way of exporting symbols when building executables (-Wl,--export-dynamic as mentioned in a comment by Brandon) but I'm not sure why you'd want to do that.
I faced the similar issue in my code.
I did the following to export symbols
#ifndef EXPORT_API
#define EXPORT_API __attribute__ ((visibility("default")))
#endif
Now for each of the function definition I used the above attribute.
For example the earlier code was
int func() { printf(" I am a func %s ", __FUNCTION__ ) ;
I changed to
EXPORT_API int func() { printf(" I am a func %s ", __FUNCTION__ ) ;
Now it works.
dlsym gives no issues after this.
Hope this works for you as well.
Im working on a project for stm32f4 to my school. Im using CooCox IDE.
I wanted to add new files "przerwania.c" and "przerwania.h" to write some functions there - not in "main.c". But I have no idea why CooCox is showing me errors.
Earlier I wanted to move some of functions from main.c to pwm.c and them work! But I would like to make a new files couse i have more functions.
Errors in CooCox look like this:
[mkdir] Created dir: D:\CooCox\CoIDE\workspace\testowy2\testowy2\Debug\obj
[cc] 12 total files to be compiled.
[cc] arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Wall -ffunction-sections -g -O0 -c -DSTM32F407VG -DSTM32F4XX -DUSE_STDPERIPH_DRIVER -D__ASSEMBLY__ -ID:\CooCox\CoIDE\workspace\testowy2 -ID:\CooCox\CoIDE\workspace\testowy2\cmsis_boot -ID:\CooCox\CoIDE -ID:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\include -ID:\CooCox\CoIDE\workspace\testowy2\cmsis -ID:\CooCox\CoIDE\workspace\testowy2\cmsis_lib -ID:\CooCox\CoIDE\workspace D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\stm32f4xx_syscfg.c D:\CooCox\CoIDE\workspace\testowy2\pwm.c D:\CooCox\CoIDE\workspace\testowy2\dupa.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_boot\startup\startup_stm32f4xx.c D:\CooCox\CoIDE\workspace\testowy2\main.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\stm32f4xx_rcc.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\stm32f4xx_adc.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\stm32f4xx_gpio.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_boot\system_stm32f4xx.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\stm32f4xx_exti.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\misc.c D:\CooCox\CoIDE\workspace\testowy2\cmsis_lib\source\stm32f4xx_tim.c
[cc] Starting link
[cc] arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -g -nostartfiles -Wl,-Map=testowy2.map -O0 -Wl,--gc-sections -LD:\CooCox\CoIDE\configuration\ProgramData\testowy2 -Wl,-TD:\CooCox\CoIDE\configuration\ProgramData\testowy2/arm-gcc-link.ld -g -o testowy2.elf ..\obj\stm32f4xx_syscfg.o ..\obj\pwm.o ..\obj\dupa.o ..\obj\startup_stm32f4xx.o ..\obj\main.o ..\obj\stm32f4xx_rcc.o ..\obj\stm32f4xx_adc.o ..\obj\stm32f4xx_gpio.o ..\obj\system_stm32f4xx.o ..\obj\stm32f4xx_exti.o ..\obj\misc.o ..\obj\stm32f4xx_tim.o
[cc] ..\obj\main.o: In function `main':
[cc] D:\CooCox\CoIDE\workspace\testowy2/main.c:336: undefined reference to `Nowafunkcja'
[cc] collect2.exe: error: ld returned 1 exit status
main.c is quite long becouse i have some definitions of few long functions there, so I paste here only a part
#include "stm32f4xx.h"
#include "misc.h"
#include "stm32f4xx_syscfg.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_exti.h"
#include "przerwania.h"//here is the problem
#include "pwm.h"
int main(void)
{
SystemInit();
//IniDiody();
//TimConfig();
//NVIC_Config();
//IniDiodyPWM();
LEDInit();
EXTILine0_Config();
PWM2();//wiwo
GPIO();//wiwo
Nowafunkcja();//PROBLEM
RCC_Konfiguracja_Adc12();
GPIO_Configuration_Adc1();
ADC1_Configuration();
GPIO_Configuration_Adc1();
GPIO_Configuration_Adc2();
ADC2_Configuration();
IniDiody(GPIO_Pin_14);
IniTimerPrzerwanie1();
while(1)
{
ADC_SoftwareStartConv(ADC1);
ADC_SoftwareStartConv(ADC2);
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);
wynikADC1 = (float)ADC_GetConversionValue(ADC1);
while(ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC) == RESET);
wynikADC2 = (float)ADC_GetConversionValue(ADC2);
wartosc = (int)(wynikADC2 * 15);
//doPWM=(((float)ADCResult) / 41);
//wartosc = (int) doPWM;
//TIM2->CCR3 = (int) doPWM;
TIM3->CCR2 = 65535;
TIM3->CCR1 = wartosc;//(int)(wynikADC2 * 15);
wartoscPrescalera=(int)SystemCoreClock;
}
}
and files:
przerwania.h
#ifndef __przerwaniah
#define __przerwaniah
void Nowafunkcja(void);
#endif
przerwania.c
#include "przerwania.h"
void Nowafunkcja(void)
{
//nothing here - just for test
}
Do you have any idea what is the problem? I'm thinking about this since yesterday and its wird :/
I'll appreciate your help!
Take a look at the line under [cc] 12 total files to be compiled.
When you added pwm.c, you also informed the compiler to include this file. You'll see it listed there. przerwania.c is not.
If you add przerwania the same way you added pwm, your IDE will take care of making sure it is included in the build.
I'm not sure what your current file/folder structure looks like:
http://www.coocox.org/CoIDE/Project_management_config.html can help you determine how to pull those new files into the build.
FWIW:
The (anthropomorphized) compiler step says: Is this valid code? So it looks though your main.c, sees that you included przerwania.h, and comes to the conclusion that you correctly used the Nowafunkcja function (just matched the signature). Even though at this point, it has NOT looked into przerwania.c to find out what it does. The compiler goes on to do this for all of your files and keeps track of what functions are defined in each file. Note that it never found the definition Nowafunkcja, because the compiler never compiled przerwania.c. It did however find the declaration in the .h (because main.c told it exactly where to find the .h)
The linker then gets this stuff from the compiler, including what functions have been defined in all your .c files. That's the first point where something tries to answer the question "Now what code do I actually need to run when he asked me to Nowafunkcja()?". So that's the first point in the build when the tools realized, I never found code for Nowafunkcja in any of the .c files I was looking in.
So, I think that roughly answers "Why", but we need to know more about your project organization to give you a "fix" to make it work.
I need to create an application to extract one file from zip archive, after which I want to compile it for Android.
I'm using Ubuntu, with libzip-0.10.1 pre-installed.
I created C project in Eclipse, added include path and found simple script for extracting file. Unfortunately I cannot get the following to build and I could use some advice.
// zip.c file
#include <stdio.h>
#include <stdlib.h>
#include <zip.h>
int main(int argc, char **argv) {
struct zip *zip_file;
struct zip_file *file_in_zip;
int err;
int files_total;
int file_number;
int r;
char buffer[10000];
if (argc < 3) {
fprintf(stderr,"usage: %s <zipfile> <fileindex>\n",argv[0]);
return -1;
};
zip_file = zip_open(argv[1], 0, &err);
if (!zip_file) {
fprintf(stderr,"Error: can't open file %s\n",argv[1]);
return -1;
};
file_number = atoi(argv[2]);
files_total = zip_get_num_files(zip_file);
if (file_number > files_total) {
printf("Error: we have only %d files in ZIP\n",files_total);
return -1;
};
file_in_zip = zip_fopen_index(zip_file, file_number, 0);
if (file_in_zip) {
while ( (r = zip_fread(file_in_zip, buffer, sizeof(buffer))) > 0) {
printf("%s",buffer);
};
zip_fclose(file_in_zip);
} else {
fprintf(stderr,"Error: can't open file %d in zip\n",file_number);
};
zip_close(zip_file);
return 0;
};
Also I added few .h files to include directory in my project and few .c files to directory with zip.c file. After that all dependences was good, but I have an error:
‘struct zip’ has no member named ‘default_password’ in file zip_fopen_index.c
The file zip_fopen_index.c is:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "zipint.h"
ZIP_EXTERN struct zip_file *
zip_fopen_index(struct zip *za, zip_uint64_t fileno, int flags)
{
return zip_fopen_index_encrypted(za, fileno, flags, za->default_password); // error here
}
First of all allow me some comments:
Your program is not compiled and linked by Eclipse.
Compiling is done by the compiler (gcc using option -c):
make all
Building file: ../zip.c
Invoking: GCC C Compiler
gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"zip.d" -MT"zip.d" -o "zip.o" "../zip.c"
Finished building: ../zip.c
Linking is done by the linker (via the compiler using option -o):
Invoking: GCC C Linker
gcc -o "unzipper" ./zip.o
./main.o: In function `zip':
/home/alk/workspace/unzipper/Debug/../zip.c:20: undefined reference to `zip_open'
/home/alk/workspace/unzipper/Debug/../zip.c:27: undefined reference to `zip_get_num_files'
/home/alk/workspace/unzipper/Debug/../zip.c:33: undefined reference to `zip_fopen_index'
/home/alk/workspace/unzipper/Debug/../zip.c:35: undefined reference to `zip_fread'
/home/alk/workspace/unzipper/Debug/../zip.c:38: undefined reference to `zip_fclose'
/home/alk/workspace/unzipper/Debug/../zip.c:43: undefined reference to `zip_close'
collect2: ld returned 1 exit status
Eclipse provides a framework helping you in managing all sources and their references as also spawing compiler and linker tasks and setting their options.
When the linker told you there where undefined references to the zip_*function during the build of your program, the cause for this was, you were missing to tell the linker (via the compiler, via Eclipse) where those zip_* functions could be found.
Those zip_* functions are located in a library, namely libzip.
So what you as the programmer need to tell the linker (via the compiler, via Eclipse) is to link those functions against what the compiler compiled from your sources.
As the result the linker is able to create a runnable program from your compiled sources together with all libraries needed. Certain libraries are know to Eclipse (and therfore to the linker) by default, for example the one containing the C standard functions, namely libc.
To get things going:
1 Remove the source files you pulled from the libzip librarie's sources from your project. Those sources had been compiled into the library libzip, which you will use in your project.
2 Tell the linker (via Eclipse) to use libzip for your project.
Do so by following the steps below:
open the project's properties
click 'C/C++ General'
click 'Path and Symbols', on the left select the 'Libraries' tab, there click 'Add' and enter zip
finally click 'OK'
3 Then try to build your program:
Building target: unzipper
Invoking: GCC C Linker
gcc -o "unzipper" ./zip.o -lzip
Finished building target: unzipper
(Please note additional option -lzip!)
If the developement version of 'libzip' had been installed properly before, you should be fine.
PS: unzipper was the name I used for the Eclispe project to produce the examples.
PSS: I used Eclipse Juno SR1