Let's say I have a struct defined in MyType.h
struct MyType {
int x;
int y;
};
And I build a lib myLib.so which exposes a function that takes the above type as a parameter.
#include "MyType.h"
extern "C" void myLibFunc(MyType myType) {
...
}
Then I update my MyType.h changing the definition of MyType to include an extra member variable.
struct MyType {
int x;
int y;
int z;
};
Now in my executable, I open myLib.so and load myLibFunc symbol from it which was built with old definition of MyType, but cast the void * returned by dlsym using a function signature that uses the new definition of MyType.
#include <dlfcn.h>
#include "MyType.h" //updated version
typedef void(*myLibFuncType)(MyType myType);
int main() {
auto myLibHandle = dlopen("myLib.so", RTLD_LOCAL | RTLD_NOW);
auto myLibFunc = (myLibFuncType) dlsym(myLibHandle, "myLibFunc");
...
return 0;
}
Is this supposed to work?
I have read this answer but could not figure out if the case presented here satisfies "compatible function pointer" requirement.
The two instance of the struct types are not compatible because the members are different. Section 6.2.7p1 of the C standard regarding compatible types states:
And since the struct types are not compatible, the function pointers are not compatible because their parameters are not compatible, as noted in the post you linked.
This means that attempting to call the function through that function pointer will trigger undefined behavior.
As a side note, casting an
void *, which is an object pointer, to a function pointer is not strictly allowed by the C standard. The man page fordlsymcontains the following example regarding the proper way to handle this: