2011-12-28 29 views
0

我有一個用於Windows的書面代碼,現在我試圖移植到Linux,但不知道它是否可行。如何回調exe中的函數? (linux)

我的問題:我試圖從共享庫中的可執行文件中回調函數。我怎麼做?

我對Linux很新,所以如果我的問題太低級,請和我一起袒護。

這是編譯輸出:

Output: 
    build/release-linux-ppc64/ioq3ded.ppc64 
    build/release-linux-ppc64/ioquake3.ppc64 
    build/release-linux-ppc64/baseq3/cgameppc64.so 
    build/release-linux-ppc64/baseq3/qagameppc64.so 
    build/release-linux-ppc64/baseq3/uippc64.so 
    build/release-linux-ppc64/missionpack/cgameppc64.so 
    build/release-linux-ppc64/missionpack/qagameppc64.so 
    build/release-linux-ppc64/missionpack/uippc64.so 

make[2]: Entering directory `/r/home7/XXX/ioquake3' 
make[2]: `build/release-linux-ppc64/ioq3ded.ppc64' is up to date. 
make[2]: `build/release-linux-ppc64/ioquake3.ppc64' is up to date. 
LD build/release-linux-ppc64/baseq3/cgameppc64.so 
LD build/release-linux-ppc64/baseq3/qagameppc64.so 
LD build/release-linux-ppc64/baseq3/uippc64.so 
LD build/release-linux-ppc64/missionpack/cgameppc64.so 
LD build/release-linux-ppc64/missionpack/qagameppc64.so 
LD build/release-linux-ppc64/missionpack/uippc64.so 

這是我跑來執行我的程序的命令,這就是爲什麼我想通「ioq3ded.ppc64」是我的可執行文件。

./ioq3ded.ppc64 +set fs_game Mod +set sv_pure 0 +set vm_game 0 +set vm_cgame 0 +set vm_ui 0 +set dedicated 1 +exec something_117.cfg 

這是代碼爲Windows:

//Called function 
__declspec(dllexport) void UnLinkLinkroutingcache(void) 
{ 
     //code 
} 

//Callback location 
#include<windows.h> 
typedef void (* fUnLinkLinkroutingcache_t)(void); 
void fUnLinkLinkroutingcache(fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache) 
{ 
    pUnLinkLinkroutingcache(); return; 
} 
fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache; 
void callUnlinkLink(void) 
{ 
    HMODULE hLib; 
    //fUnLinkLinkroutingcache_t pUnLinkLinkroutingcache; 

    hLib = LoadLibrary(TEXT("ioquake3.exe")); 
    if (hLib == NULL) 
     { 
     //Module not found, permission denied, ... 
     return 0; //inform caller of error 
     } 

    pUnLinkLinkroutingcache = (fUnLinkLinkroutingcache_t)GetProcAddress(hLib, TEXT("UnLinkLinkroutingcache")); 
    if (pUnLinkLinkroutingcache == NULL) 
    { 
     return 0; 
    } 

    fUnLinkLinkroutingcache(pUnLinkLinkroutingcache); 
} 

我試圖端口的代碼到Linux,但我似乎無法加載exe文件。

//Called function 
extern void UnLinkLinkroutingcache(void) 

//Callback location 
void callUnlinkLink(void) 
{ 
    void* handle; 
    void (*initializer)(void); 
    FILE *fp;//zgzg2020 

    fp = fopen("HereIsMe.txt", "a"); 
    if(fp != NULL) 
    { 
     fprintf(fp, "%d", 1); 
     fprintf(fp, "\n"); 
    } 
    fclose(fp); 

    handle = dlopen("./ioq3ded.ppc64", RTLD_LAZY); 
    if(handle == NULL) { 
     // report error ... 
     fp = fopen("ICantFindFile.txt", "a"); 
     if(fp != NULL) 
     { 
      fprintf(fp, "%d", 1); 
      fprintf(fp, "\n"); 
     } 
     fclose(fp); 
     exit(1);return; 
    } else { 
     initializer = dlsym(handle,"UnLinkLinkroutingcache"); 
     if(initializer == NULL) { 
      // report error ... 
      fp = fopen("ICantFindFfunction.txt", "a"); 
      if(fp != NULL) 
      { 
       fprintf(fp, "%d", 1); 
       fprintf(fp, "\n"); 
      } 
      fclose(fp); 
      exit(1);return; 
     } else { 
      // cast initializer to its proper type and use 
      (*initializer)(); 
     } 
     // use the result in a call to dlsym 
    } 
} 
+0

ioq3ded.ppc64是一個庫嗎? – dicaprio 2011-12-28 05:55:17

+2

'dlerror'會給你更多關於錯誤的信息。而不是'fprintf(fp,「%d」,1);'try'fprintf(fp,「%s」,dlerror());'並檢查文件。正如duskwuff在迴應中已經提到的那樣,'dlopen'不適用於可執行文件。 – 2011-12-28 06:01:23

+0

我試過fprintf(fp,「%s」,dlerror());現在:]收到信號11,正在退出... -----服務器關閉(信號被捕獲)----- – user598208 2011-12-28 08:49:30

回答

1

你可以在Linux中不是dlopen可執行文件 - 該功能僅適用於共享庫(.so,大致相當於.dll在Windows上)。

你想完成什麼?

+0

感謝您解決這個問題。我正試圖從外部* .so文件中調用可執行文件內部的函數。我怎麼做? – user598208 2011-12-28 08:45:55

+0

對於外部可執行文件中的函數,你不能這麼做(因爲它沒有多少意義)。 – 2011-12-28 10:24:59

0

函數dlopen()加載由以null結尾的字符串文件名命名的動態庫文件,併爲動態庫返回一個不透明的「句柄」。如果文件名爲NULL,則返回的句柄用於主程序。這意味着它必須是動態庫。

+0

對不起,我不明白你想說什麼...... :( – user598208 2011-12-28 08:51:33

0

如果ioq3ded.ppc64真的是.so(看起來不是這樣),你有沒有檢查它的輸出?

當你從dlopen得到一個null返回時,你是否檢查過errno(假設這裏是一個.so文件,就像@duskwuff所說的,其他所有東西都會失敗)?

+0

我試圖在標題中說明它,我試圖從外部調用EXE內部的函數。 – user598208 2011-12-28 08:46:55

+1

把它放在一個共享庫中,而不是二進制文件中,實際上沒有其他(好的)方法。對於標題,我認爲它是一個錯字 – Fredrik 2011-12-28 09:03:35

+0

我太綠了,不敢嘗試在Linux庫創作中冒險。 。><其他建議? – user598208 2011-12-28 09:26:07

2

不幸的是,dlopen不足以達到此目的,正如許多其他海報所說。它只能加載共享庫。如果您傳遞的是NULL而不是共享庫路徑,則可以查找運行時鏈接程序未從主可執行映像中刪除的任何符號(並不是很多)。然而,如果你想調用編譯時沒有-rdynamic的可執行文件中的函數,請嘗試LD_PRELOAD'ing你自己的共享庫(在啓動時)通過/proc/self/exe定位到你的可執行文件的真實路徑,內存映射它,然後讀取映射(或其他可執行頭文件)上的符號表來定位和解釋主可執行文件中的符號。

從那裏開始,只需在共享庫中定義幾個函數指針,它們與您希望調用的函數的原型相匹配,將它們分配給二進制文件中的符號位置,然後將函數指針調用爲正常。

+0

我用「-rdunamic」再次編譯它,然後handle = dlopen(NULL,RTLD_LAZY); //但是,保持崩潰...><。我可以嘗試「LD_PRELOAD」,但「共享庫」是可執行文件,我怎麼先加載它? – user598208 2011-12-28 09:13:58

+0

「它保持崩潰「不解釋在問題中。我想你正在用一些不好的假設來解決這個問題。你應該更新你的問題,更好地解釋你想要完成的事情。 – jmkeyes 2011-12-29 02:24:37