Having ./library.so (`rary.cpp`) and ./main (`main.cpp`) executable, both sharing the same `api.h`.

The only method (`void method (void)`) has only its signature in `api.h`, the actual implementation is in `main.cpp`.

At compile time `rary.cpp` doesn't include the actual definition of the method: `main.cpp` is never mentioned when making the `library.so` file. Still if I access the shared file via `dlopen` and `dlsym`, any calls from within `library.so` to the method do actually refer to the method which was only implemented in the main program.

I didn't expect this to happen, as far as I am aware `library.so` was never present in the implementation of the method, so the compiler (I think) should complain that a not-implemented method is being called.

So my questions are:

1. Is this normal? are methods implemented in the main binary supposed to be accessed directly from dynamically loaded modules just by their name? (I thought that there is no guarantee of how symbols can be actually called in a binary after compiling)
2. Is there a way to prevent this? Say that I am providing an API for someone to write a plugin for my program, this way they could guess the names of the methods in the main binary and do some... hack?
3. Can I expect this behavior to be consistent between compilers and operating systems?
4. Should I or is it a good practice to rely on this behavior?

---

Source codes
============

main.cpp
--------

```
#include "api.hpp"
#include <iostream>
#include <dlfcn.h>

using std::cout;
using std::endl;

void method (void)
{
    cout << "method happened" << endl;
}

void method (int num)
{
    cout << "method happened with num " << num << endl;
}

int main (void)
{
    cout << "started main" << endl;

    typedef void(* initfunc)();

    void * handle = dlopen("./library.so", RTLD_LAZY);

    initfunc func = reinterpret_cast<initfunc> (dlsym(handle, "init"));

    func();

    return 0;
}

```

rary.cpp
--------

```
#include "api.hpp"
#include <iostream>

using std::cout;
using std::endl;

extern "C" void init (void)
{
    method();
    method(69);
    cout << "library ran" << endl;
}

```

api.h
-----

```
void method (void);
void method (int);

```

CMakeLists.txt
--------------

```
project(apitest CXX)

add_executable(apitest "main.cpp")
add_library(rary MODULE "rary.cpp")
target_link_libraries(apitest dl)

```

Compiling
---------

```
cmake .
make

```

Result
------

```
$ ./apitest
started core
method happened
method happened with num 69
library ran

```