This is a question on C/C++ function definitions. The code discussed is the static library libRmath that provides the definitions in the Rmath.h header file in R.
The documentation provided for the library states that it is optional for the user to provide the function definition for the function double unif_rand(void).
So my question is if such a function definition is optional, wouldn’t there be a problem of multiple function definitions which is not allowed in C/C++?
Edit:
It might be tempting to speculate on how things works without looking at the source code, but that is not what I want. I am interested to know how it really works, so you would probably need to read the source code and documentations to answer this question.
When you application is linked, unresolved symbols will be resolved using the libraries you provide. If you don’t define a function, it will be an unresolved symbol during linking, therefore, the linked will try to resolve that symbol using librmath, in this case. If one or more symbols can’t be resolved, you’ll get a linker error.
However, if you do define the function in your code, it will be already defined during linking, so there will be no need to resolve it using symbols from external libraries.
What you can’t do is to define the same symbol more than once in your application.
Edit: Since there is a lot of debate in another answer, i’ve made a practical example. I’ve created a shared object(similar to a DLL in windows), which defines and exports a function
foo:In order to test this shared object, i’ve created an application which is linked with it:
I’ve compiled both, the shared object and the application:
And when i execute
test, setting the library path to".", so my shared object can be loaded, i get this output:As you can see, the
foofunction defined in the application(not the shared object) is called. You can basically do this for every exported symbol in a shared object.EDIT2: i’ve added another exported function in lib.h. The application now calls this function, which ends up calling foo. The result is the same, as expected.
EDIT3: Ok, let’s go deeper. This is the dump from function
bar:If we go to address
0x804a004:As you can see, it’s jumping to the Global Offset Table. You can read about the GOT here and here. Dynamic symbols(which are resolved at runtime) are stored in this table. Whenever you call a symbol that should be resolved at runtime, you actually jump to this table, and then jump to the address that is stored in the this table’s corresponding entry. Since the application defines
foo, the GOT contains the address of the definition fromtest.cpp, not the one in our shared object.EDIT4: Okay, last edit. Quoting from the documentation:
The documentation clearly says that you cannot provide you own implementation of
unif_randif you’re using the dynamic library. Therefore, i believe that what i pointed out, actually answers your question.