I was trying to write a basic example of shared library opening and function calling for practice, but it turns out that I always get "segmentation fault" when the exectuable is actually running. Here are the source code:
main.cpp:
#include<iostream>
#include<dlfcn.h>
using namespace std;
typedef void (*API)(unsigned int);
int main(int argc,char** argv){
void* dl;
API api;
unsigned int tmp;
//...
dl=dlopen("pluginA.so",RTLD_LAZY);
api=(API)dlsym(dl,"API");
cin>>tmp;
(*api)(tmp);
dlclose(dl);
//...
return 0;
}
pluginA.cpp:
#include<iostream>
using namespace std;
extern "C" void API(unsigned int N){switch(N){
case 0:cout<<"1\n"<<flush;break;
case 1:cout<<"2\n"<<flush;break;
case 2:cout<<"4\n"<<flush;break;
case 4:cout<<"16\n"<<flush;break;}}
I compiled the two part with the following command:
g++ -shared -o pluginA.so -fPIC plugin.cpp
g++ main.cpp -ldl
Here is the output
Segmentation fault (core dumped)
BTW, I also tried directly call api(tmp) rather than (*api)(tmp), that also don't work. Since api is a pointer, (*api) makes more sense?
I'm not sure what should I do. There are many totorials about calling function in shared library online, but most of them aren't fully coded, or they actually don't work.
And also I'm not sure what should I do with "attribute((visibility("default")))". Should I even write it down?
EDT1 Thanks for giving me so much advice. I finally find out that actually everything is a typo in compiling command... I mistakenly typed pluginA.so to pluginA.o, and that's the reason why it don't work...
Anyway, here is my revised program, with error handling added, and more "full" system added:
main.cpp:
#include<dirent.h>
#include<dlfcn.h>
#include<iostream>
#include<cstring>
using namespace std;
typedef bool (*DLAPI)(unsigned int);
int main(){
DIR* dldir=opendir("dl");
struct dirent* dldirf;
void* dl[255];
DLAPI dlapi[255];
unsigned char i,dlc=0;
char dldirfname[255]="./dl/";
unsigned int n;
while((dldirf=readdir(dldir))!=NULL){
if(dldirf->d_name[0]=='.')continue;
strcat(dldirfname,dldirf->d_name);
dl[dlc]=dlopen(dldirfname,RTLD_LAZY);
if(!dl[dlc])cout<<dlerror()<<endl;else{
dlapi[dlc]=(DLAPI)dlsym(dl[dlc],"API");
if(!dlapi[dlc])cout<<dlerror()<<endl;else dlc++;}
dldirfname[5]='\0';}
if(dlc==0){
cerr<<"ERROR:NO DL LOADED"<<endl;
return -1;}
while(true){
cin>>n;
for(i=0;i<dlc;i++)if((*dlapi[i])(n))break;
if(i==dlc)cout<<"NOT FOUND"<<endl;}
for(i=0;i<dlc;i++)dlclose(dl[i]);
return 0;}