In my main.c , i have :
int myvar[4] = {0,1,2,3};
int main(int argc, char *argv[])
{
...................
}
When I try to access myvar in another file as below:
extern int myvar[4];
if (myvar[0] == 1) do something;
When I build this (after cleaning the project), errors "LNK2001: unresolved external symbol _myvar" and "fatal error LNK1120: 1 unresolved externals" are observed. But if I comment the 'if' statement alone, then the solution builds fine and I can observe the correct values for myvar in the watch window in debug mode. I am confused regarding why this is happening. Any help would be highly appreciated!
Since you mention in your comment that the usage is split up into two different libs, you need to set up a dependency for the using library (the one that has extern int myvar[4];) to the providing library (the lib providing the main function and declaring int myvar[4]).
However, this could lead you into the problem that you have circurlar dependencies: usually the library providing the main function will call some functions in other libraries.
If you need myvar in your using library, then pass it down with an init function that gets called in order to initialize the using library.
An example for your work to be done assuming that the main() function is provided by lib_a and the library accessing myvar is called lib_b:
In lib_a do the following:
int main(int argc, char *argv[])
{
lib_b_init(sizeof(myvar)/sizeof(*myvar), myvar);
/* rest of your code goes here */
}
In lib_b in addition to the functions already provided, add the following:
static int* g_libb_myvar = (int*) 0; /* local pointer to myvar of lib_a */
static int g_libb_myvar_size = 0; /* to note the length of the array */
/* Initializer for lib_b
*
* #param a_count number of elements held in the a_myvar array
* #param a_myvar array getting passed down by caller
* */
void lib_b_init( int a_count, int* a_myvar ) {
g_libb_myvar_size = a_count;
g_libb_myvar = a_myvar; /* now, you could use g_libb_myvar in lib_b */
}
Related
In C90, can I redefine main and give it another name, and possibly add extra parameters using #define?
Have this in a header file for example:
#include <stdio.h>
#include <stdlib.h>
#define main( void ) new_main( void )
int new_main( void );
The header doesn't show any errors when compiling.
When I try compiling it with the main C file, however, I keep getting an error
In function '_start': Undefined reference to 'main'
No, you cannot do that, because it would be against language and OS standards. The name main and its arguments argc, argv and environ constitute a part of system loader calling conventions.
A bit simplifying explanation (no ABI level, just API level) ensues. When your program has been loaded into memory and is about to start, the loader needs to know which function to call as an entrypoint, and how to pass its environment to it. If it was be possible to change the name of main and/or its parameter list, it would have been needed to communicate details of new calling interface back to the loader. And there is no convenient way to do it (apart from writing your own executable loader).
In function '_start': Undefined reference to 'main'
Here you can see an implementation detail of Linux/POISX ELF loader interface. The compiler adds function _start to your program behind the scenes, which is an actual program entrypoint. _start is tasked to do extra initialization steps common to most programs that use LibC. It is _start that later calls your main. Theoretically, you could write a program that has its own function called _start and no main and it would be fine. It is not trivial as you will have to make sure that the default _start code is no longer being attached to your program (no double definitions), but it is doable. And no, you cannot choose other name than _start for the same reasons.
The presence of #define main new_main within a compilation unit will not affect the name of the function the implementation will call on program startup. The implementation is going to call a function called main regardless of any macros you define.
If you are going to use a #define like that to prevent the primary declaration of main() from producing a function by that name, you'll need to include a definition of main() somewhere else; that alternate version could then invoke the original. For example, if the original definition didn't use its arguments, and if the program exits only by returning from main() [as opposed to using exit()] you might put #define main new_main within a header file used by the primary definition of main, and then in another file do something like:
#include <stdio.h>
#include <conio.h> // For getch() function.
int main(void)
{
int result = main();
printf("\nExit code was %d. Strike any key.\n", result);
getch();
return result;
}
In most cases, it would be better to add any such code within the ordinary "main" function, but this approach can be useful in cases where the file containing main is produced by code generation tools on every build, or for some other reason cannot be modified to include such code.
No you cannot (as Grigory said).
You can however, immediate call your proxy main,
int
your_new_main(int argc, char* argv[], char* envp[]) {
... //your stuff goes here
}
//just place this in an include file, and only include in main...
int
main( int argc, char* argv[], char* envp[])
{
int result = your_new_main(argc, argv);
return result;
}
As far as whether envp is supported everywhere?
Is char *envp[] as a third argument to main() portable
Assuming you're using gcc passing -nostdlib to your program, and then set a new entry, by passing this to gcc which passing it to the linker, -Wl,-enew_main. Doing this won't give you access to any of the nice features that the C runtime does before calling your main, and you'd have to do it yourself.
You can look at resources about what happens before main is called.
What Happens Before main
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();
}
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);
...
Is it possible to assign with cast to a function pointer a string or char array and then run it?
I have defined a few functions int f1();, int f2();, and so on
In the main() function I have read a string fct_name and declared a pointer to function int (*pv)();
I need to do something like this:
the fct_name can have values "f1" , "f2" and so on..
pv = (some sort of cast)fct_name;
pv();
My point is I want to avoid conditional instructions in favor of direct assignment (because I have a large number of functions in my program)
The code must obviously run.
Assuming you don't have an external library and are trying to call functions declared in your executable, you can do a lookup yourself
#define REGISTER_FUNC(name) {#name, name}
struct funclist
{
const char* name;
void (*fp)(void); //or some other signature
};
struct funclist AllFuncs[] = {
REGISTER_FUNC(f1),
REGISTER_FUNC(f2),
REGISTER_FUNC(f3),
{NULL,NULL} //LAST ITEM SENTINEL
};
Now you can lookup your variable fct_name in AllFuncs. You can use a linear search if the number is small, or insert them all into a hash table for O(1) lookup.
Alternately, if your names really are f1, f2, etc. you can just do
void (*FuncList)(void)[] = {NULL, f1,f2,f3};
...
int idx = atol(fct_name+1);
if (idx && idx < MAX_FUNCS)
FuncList[idx]();
A variant of Carey's answer, in case you're on a *nix system. dlopen() opens up your library. RTLD_LAZY tells the loader to not bother resolving all the library's symbols right away, and to wait for you to try to access them. dlsym() looks up the symbol in question.
Edit: Updated the snippet to better fit your clarification:
#include <dlfcn.h>
int main(int argc, char *argv[])
{
void *handle = dlopen("libexample.so", RTLD_LAZY);
if (handle == NULL) {
// error
}
char fct_name[64];
// read input from terminal here
void *func = dlsym(handle, fct_name);
if (func != NULL) {
// call function here; need to cast as appropriate type
}
}
libexample.so would be a library with your functions, compiled as a shared library, like so:
gcc -Wall -o libexample.so example.c -shared -fPIC
That being said, if you're going to the trouble of compiling a shared library like this, you'll probably just want to call the functions in your binary. You can do that if you link your library in at compile-time:
gcc -Wall -o test test.c -L. -lexample
-L. tells the linker to look for libraries in the current directory (.) and -lexample tells it to link with a library named "libexample.so". If you do this, you can just call the library functions directly within your program.
You can't cast a char array to a function just because the array happens to contain the name of a function. What you need to do is put your function(s) in a DLL and then do this:
HMODULE dll = LoadLibrary("foo.dll");
pv func = (pv)GetProcAddress(module, fct_name);
When loaded a shared library is opened via the function dlopen(), is there a way for it to call functions in main program?
Code of dlo.c (the lib):
#include <stdio.h>
// function is defined in main program
void callb(void);
void test(void) {
printf("here, in lib\n");
callb();
}
Compile with
gcc -shared -olibdlo.so dlo.c
Here the code of the main program (copied from dlopen manpage, and adjusted):
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
void callb(void) {
printf("here, i'm back\n");
}
int
main(int argc, char **argv)
{
void *handle;
void (*test)(void);
char *error;
handle = dlopen("libdlo.so", RTLD_LAZY);
if (!handle) {
fprintf(stderr, "%s\n", dlerror());
exit(EXIT_FAILURE);
}
dlerror(); /* Clear any existing error */
*(void **) (&test) = dlsym(handle, "test");
if ((error = dlerror()) != NULL) {
fprintf(stderr, "%s\n", error);
exit(EXIT_FAILURE);
}
(*test)();
dlclose(handle);
exit(EXIT_SUCCESS);
}
Build with
gcc -ldl -rdynamic main.c
Output:
[js#HOST2 dlopen]$ LD_LIBRARY_PATH=. ./a.out
here, in lib
here, i'm back
[js#HOST2 dlopen]$
The -rdynamic option puts all symbols in the dynamic symbol table (which is mapped into memory), not only the names of the used symbols. Read further about it here. Of course you can also provide function pointers (or a struct of function pointers) that define the interface between the library and your main program. It's actually the method what i would choose probably. I heard from other people that it's not so easy to do -rdynamic in windows, and it also would make for a cleaner communication between library and main program (you've got precise control on what can be called and not), but it also requires more house-keeping.
Yes, If you provide your library a pointer to that function, I'm sure the library will be able to run/execute the function in the main program.
Here is an example, haven't compiled it so beware ;)
/* in main app */
/* define your function */
int do_it( char arg1, char arg2);
int do_it( char arg1, char arg2){
/* do it! */
return 1;
}
/* some where else in main app (init maybe?) provide the pointer */
LIB_set_do_it(&do_it);
/** END MAIN CODE ***/
/* in LIBRARY */
int (*LIB_do_it_ptr)(char, char) = NULL;
void LIB_set_do_it( int (*do_it_ptr)(char, char) ){
LIB_do_it_ptr = do_it_ptr;
}
int LIB_do_it(){
char arg1, arg2;
/* do something to the args
...
... */
return LIB_do_it_ptr( arg1, arg2);
}
The dlopen() function, as discussed by #litb, is primarily provided on systems using ELF format object files. It is rather powerful and will let you control whether symbols referenced by the loaded library can be satisfied from the main program, and generally does let them be satisfied. Not all shared library loading systems are as flexible - be aware if it comes to porting your code.
The callback mechanism outlined by #hhafez works now that the kinks in that code are straightened out.