Linker error when using a struct variable - c

When I try to compile the program below, I get a linker error:
/tmp/ccAikIsV.o undefined reference to uvlc_encode_blockline
I have all the structures video_controller_t .. etc declared and typedefed
int uvlc_encode_blockline(struct video_controller_t* controller, const struct vp_api_picture_t* blockline, bool_t picture_complete );
int uvlc_decode_blockline(struct video_controller_t* controller,struct vp_api_picture_t* picture, bool_t* got_image );
int uvlc_update( struct video_controller_t* controller );
int uvlc_cache( struct video_controller_t* controller,struct video_stream_t* ex_stream);
const uvlc_codec_t uvlc_codec = {
uvlc_encode_blockline,
uvlc_decode_blockline,
uvlc_update,
uvlc_cache,
{ 0 }
};
Please let me know if anyone has any suggestions.
Update
I agree that we should define the function to tell linker to get it and use it. When I did something similar, I did not get any error. I declared function pointer:
typedef C_RESULT (encode_blockline_fc)(struct video_controller_t controller,
const struct vp_api_picture_t* blockline,
bool_t picture_complete);
and used it in struct below:
typedef struct _video_codec_t
{
encode_blockline_fc encode_blockline;
decode_blockline_fc decode_blockline;
update_fc update;
cache_stream_fc cache_stream;
} video_codec_t;
Please let me know if there is anything wrong in the syntax below:
const uvlc_codec_t uvlc_codec = {
uvlc_encode_blockline,
uvlc_decode_blockline,
uvlc_update,
uvlc_cache,
{ 0 }
};
I agree that we should define the function to tell linker to get it and use it. when I did something similar, I did not get any error. I declared function pointer
typedef C_RESULT (encode_blockline_fc)( struct video_controller_t controller, const struct vp_api_picture_t* blockline, bool_t picture_complete );
and used it in struct below
typedef struct _video_codec_t { encode_blockline_fc encode_blockline; decode_blockline_fc decode_blockline; update_fc update; cache_stream_fc cache_stream; }video_codec_t
Please let me know if there is anything wrong in the syntax below:
const uvlc_codec_t uvlc_codec = {
uvlc_encode_blockline,
uvlc_decode_blockline,
uvlc_update,
uvlc_cache,
{ 0 }
};

The linker complains about an unresolved reference to a function, not about the struct. You should pass the linker an object file or a library that contains this function, or define it in the current compilation unit.

There are few possibility of Linker Error-
1- If you fail to include all of the necessary object files in the linking process.
2- If there are more than one definition for a class, function, or variable.
So check it.

You've told the compiler that the function uvlc_encode_blockline() exists somewhere, but when the linker goes to look for it, it can't actually find it — so it complains that it can't find it.
The declaration is enough to let the source file compile to object code. To link the program, you actually have to define the function and link the object file that contains the definition in with the object file that references it.

Related

Pointer to a static variable inside a function. C

I have 3 files in my directory:
ex22.h, ex22.c. ex22_main.c
ex22.h:
#ifndef _ex22_h
#define _ex22_h
extern double* v;
...
#endif
ex22.c:
#include <stdio.h>
#include "ex22.h"
double* v;
/*a function that accepts a new_variable, changes a
static variable inside of it while keeping track of
what the static variable was before the change. The
purpose of the function is to update the static
variable and print what it was right before the
updating.*/
double update_variable(double new_variable)
{
static double variable = 1.0;
double old_variable = variable;
variable = new_variable;
v = &variable;
return old_variable;
}
...
ex22_main.c:
#include "ex22.h"
#include "dbg.h"
...
int main(void)
{
//test if it is possible
printf("Variable at first: %f", update_variable(2.0);
printf("Access 'variable' inside update_variable: %f", *v);
}
Compiller (ubuntu) gives me those error messages:
cc ex22_main.c -o ex22_main
/tmp/ccGLFiXP.o: In function `main':
...
ex22_main.c:(.text+0x1f4): undefined reference to `update_variable'
ex22_main.c:(.text+0x222): undefined reference to `r'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'ex22_main' failed
make: *** [ex22_main] Error 1
Hope you understood what I'm trying to achieve. My goal is to access the static variable inside a function (which is not possible) by making a pointer to it. I'm just curious if it works that way?
EDIT:
There were some stupid bugs in my code but the idea of accessing a static variable inside a function by it's pointer is completely feasible.
Avoid my mistakes:
1) Make sure files are linked
2) Watch out for variable names
My goal is to access the static variable inside a function (which is not possible) by making a pointer to it. I'm just curious if it works that way?
Yes, it does. static has a different meaning for variables declared inside functions than for those declared at file scope, but but both varieties exist and have the same address for the entire lifetime of the program. A pointer to such a variable can be used to access its value anywhere in the program, without regard to whether the variable can be accessed via its declared identifier at the point of access-via-pointer.
Your compilation issue is unrelated. Your other answer explains the nature of that problem.
The compiler, or more precisely the linker, can't find the definitions of update_variable or r because you didn't compile and link ex22.c which contains those definitions.
You need to compile both files and link them together.
cc -o ex22_main ex22_main.c ex22.c

Extern Variables seemingly not working "symbols not found for architecture x86_64"

I've been searching through Stackoverflow and the web for the answer and it seems like I'm doing this correctly, however I can't get it to work.
I made a test program for using extern, (it's on xCode using the projects feature if that makes a difference). I'm trying to declare a variable, that I can access anywhere in my program, whenever I change the value of that variable, I want to be able to access the changed value.
What I've done so far is I have a header file
externFile.h
and a
externFile.c
and of course my
main.c
In externFile.h I defined:
extern int ply;
In main.c I have:
int main()
{
int ply;
ply = 5;
printPly();
}
In externFile.c I have:
void printPly(){
printf("%d is ply.\n", ply);
}
However I'm getting this error:
_ply referenced from _printPly
ld symbols not found for architecture x86_64
Does anyone have any sort of ideas about this?
You haven't actually defined ply globally:
int main(void)
{
int ply;
ply = 5;
printPly();
}
Here, ply is a local variable, not a global, since it is defined inside of a function. The extern line in your header file does not define the global, but declares it. It says "this variable exists somewhere", but it doesn't create it. Because there is no global defined, you get an undefined reference error.
Global variables must be defined at file scope, i.e. outside of a function:
int ply = 5;
int main(void)
{
printPly();
}

Link to a DLL in Pelles C

I have a 218KB .dll and a 596KB .so file, both with identical names. I want to link to the .dll to avoid the "unresolved external symbol" error that the linker returns, but I can't find a way to link to the DLL file.
According to this Pelles C forum topic, I need to use the .def file to create a .lib... but I don't have a .def file. This forum topic shows how to use polink to create a .lib from the command line, so I ran polink /? to get some more options. I noticed a /MAKEDEF option, but running this with both the .dll and the .so gives a "No library file specified" fatal error.
I have been trying to do this for three hours, and am out of ideas. I have got to the point where my web searches turn up my own help-requests. There must be a way to do this... How can I link to a .dll?
With information found in the header #include and your details, here is a way to replace the missing function by calling them dynamically from your software.
1- the following prototype is in #include :
typedef float (* XPLMFlightLoop_f)(float inElapsedSinceLastCall, float inElapsedTimeSinceLastFlightLoop, int inCounter, void * inRefcon);
2- some const that you can fill as needed:
const char *sDllPathName = "<Your XPLM_API DLL>.dll";
const char *sXPLMRegisterFlightLoopCallbackName = "XPLMRegisterFlightLoopCallback";
In order to confirm the sXPLMRegisterFlightLoopCallbackName, you can
use the freeware Dependency Walker and check name and format of
the exported functions.
3- declare the prototype of the external function:
Be aware to the calling convention __cdecl or __stdcall
In the current case, the keyword XPLM_API is defined in the XPLMDefs.h as follow:
#define XPLM_API __declspec(dllexport) // meaning __cdecl calling convention
typedef void (__cdecl *XPLMRegisterFlightLoopCallback_PROC)(XPLMFlightLoop_f, float, void *);
4- clone the function to call it in your software:
#include <windows.h>
void XPLMRegisterFlightLoopCallback(XPLMFlightLoop_f inFlightLoop, float inInterval, void * inRefcon)
{
HINSTANCE hInstDLL;
XPLMRegisterFlightLoopCallback_PROC pMyDynamicProc = NULL;
// Load your DLL in memory
hInstDLL = LoadLibrary(sDllPathName);
if (hInstDLL!=NULL)
{
// Search for the XPLM Function
pMyDynamicProc = (XPLMRegisterFlightLoopCallback_PROC) GetProcAddress(hInstDLL, sXPLMRegisterFlightLoopCallbackName);
if (pMyDynamicProc != NULL)
{
// Call the XPLM Function with the orignal parameter
(pMyDynamicProc)(inFlightLoop,inInterval,inRefcon);
return;
}
}
// Do something when DLL is missing or function not found
}
5- just add your described call:
...
XPLMRegisterFlightLoopCallback(callbackfunction, 0, NULL);
...

Optimizing away unused function pointers

I want gcc to optimize away unused function pointers. Ie remove the code completely from the final executable. So far I was not able to achieve this.
Here is updated code:
#include <stdio.h>
struct inner {
void (*fun)(void);
void (*fun2)(void);
};
struct inner2 {
void (*fun)(void);
};
struct foo {
struct inner in;
struct inner2 in2;
};
void lessfun(){
printf("lessfun\n");
}
void morefun(){
printf("morefun\n");
}
const struct foo inst = {
{ .fun = lessfun, .fun2 = morefun },
{ .fun = lessfun }
};
void test(struct foo *f){
f->in.fun();
}
int main(int argc, char *argv){
struct inner2 in = inst.in2;
inst.in.fun();
inst.in.fun2();
in.fun();
/////////////// alt1: nm out | grep morefun -> found
test(&inst);
///////////////
/////////////// alt2: nm out | grep morefun -> not found
struct inner in;
struct inner in2 = inst.in;
in = in2;
test(&in);
///////////////
}
compiler flags: -Os -fdata-sections -Wl,--relax,--gc-sections -ffunction-sections
link flags: -flto -Os -fdata-sections -Wl,--relax,--gc-sections
Compiler: arm-none-eabi-gcc
Here the compiler will include both method1 and method2 into the final program even if they are never used. It is the assignment that seems to make this happen. But if they are never called, it would be nice to completely remove the code to method1 and method2. This obviously happens because technically the function is in fact referenced in the assignment, but since the variable in the assignment is never user it should still be possible to determine that the method is never called.
Do I need to declare it const somehow? How?
How can I have gcc remove the unused functions?
EDIT: I was able to sort of make it work as you see above. But it only works if I do not make a copy of any members of the struct. If a direct copy is made and passed to a function, the compiler fails to optimize unused functions. I'm now 60% certain that this is some kind of optimizer bug.
EDIT2: you may not even reproduce the bug. But here is the scenario that creates it.
struct mydev dev;
struct dev_spi spi;
struct dev_spi sp2 = board.spi0;
sp2.writereadbyte(0);
spi = sp2;
//test(&cpu.spi0);
// using only this call results in correct optimization
// many unused methods pointed to by members of "board" var are gone.
mydev_init(&dev, &spi);
// using this version breaks optimization
// all methods referenced by "board" struct are included in final program
mydev_init(&dev, &sp2);
// this one breaks optimization as well
// same as above.
mydev_init(&dev, &board.spi0);
// there is no difference other than one passes variable directly to the init function
// and the other uses a temp variable.

Initialize a structure with a set of constant structures in C

I'm writing a device driver in MSVC. As part of design I want to have different modules but have the modules somewhat isolated from each other so that they are interchangeable in the future. My design has a structure with the following declaration
typedef struct tagMODULE_INTERFACE {
NTSTATUS (*initialize)(GLOBAL_DATA *pGD);
NTSTATUS (*shutdown)(void);
NTSTATUS (*sendResponse)(PVOID outBuf, ULONG outBufSz, PULONG outBufLen);
} MODULE_INTERFACE, *PMODULE_INTERFACE;
In the main .c file I have my main array of modules to load at install time. It is defined as such:
MODULE_INTERFACE modules[2] =
{
Module1,
{NULL, NULL, NULL}// terminal entry
};
In my module1.c file I expose the following:
CONST MODULE_INTERFACE Module1 = {initializeModule1, shutdownModule1, sendModule1Response};
In my module1.h file I have:
extern CONST MODULE_INTERFACE Module1;
The idea here is that I don't have to declare initializeModule1, shutdownModule1 and sendModule1Response functions outside of module1.c, but the main.c will have an array of function pointers to use to initialize, shutdown and callback whenever necessary.
My problem is that I'm getting a C2099 "initialize is not a constant" error for the Module1 entry in modules and I'm getting C2078 "too many initializers" for the {NULL, NULL, NULL} entry.
What am I missing here? I thought originally that if I ensured that module1.c compiled ahead of main.c it would solve the first problem, but it didn't.
Any help would be greatly appreciated.

Resources