2012-07-12 80 views
0

我正試圖編寫一個程序來調用Android中我的.so庫中的函數。爲什麼我無法使用在.so庫中聲明的函數?

main.cpp中:

#include <stdio.h> 
#include <dlfcn.h> 
#include <stdlib.h> 

typedef int (*test_ptr)(int, int); 

int main() 
{ 
    int rc; 
    void *handle; 
    const char *error; 

    handle = dlopen("./testdll.so", RTLD_LAZY); 
    if(!handle){ 
     printf("dlopen %s\n", dlerror()); 
     return -1; 
     } 
    printf("dlopen success.\n"); 

    test_ptr test = (test_ptr)dlsym(handle, "max"); 
    error = dlerror(); 
    if (error) { 
     printf("error %s\n", error); 
     dlclose(handle); 
     return -1; 
    } 
    rc = test(10, 20); 
    printf("rc = %d\n", rc); 

    dlclose(handle); 
    return 1; 
} 

testdll.cpp:

#include<stdio.h> 

int max(int x,int y){ 
    return x>y?x:y; 
} 

Android.mk:

LOCAL_PATH:= $(call my-dir) 
include $(CLEAR_VARS) 
LOCAL_SRC_FILES:= \ 
    testdll.cpp 
LOCAL_MODULE_TAGS := optional 
LOCAL_PRELINK_MODULE := true 
LOCAL_LDFLAGS := -Wl,--export-dynamic 
LOCAL_MODULE:= testdll 
include $(BUILD_SHARED_LIBRARY) 

include $(CLEAR_VARS) 
LOCAL_SRC_FILES:= \ 
    main.cpp 
LOCAL_LDLIBS := -ldl 
LOCAL_SHARED_LIBRARIES := \ 
libcutils \ 
libdl 
LOCAL_MODULE_TAGS := optional 
LOCAL_PRELINK_MODULE := true 
LOCAL_MODULE := mytest 
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) 
include $(BUILD_EXECUTABLE) 

我用,使文件,推動testdll .so in到/system/libmytest/data/data

然後我跑./mytest,它可以開放testdll.so successed,但無法連接我的功能。

錯誤是:

Symbol not found: 

有人知道如何解決這個問題?

============================================== ============================================

謝謝大家!

我打電話給我的功能成功使用extern「C」

但現在,我更改爲使用C++編寫.so庫並得到相同的錯誤消息。

testdll.cpp:

#include <sys/types.h> 
#include <unistd.h> 
#include <grp.h> 

#include <binder/IPCThreadState.h> 
#include <binder/ProcessState.h> 
#include <binder/IServiceManager.h> 
#include <utils/Log.h> 

#include <private/android_filesystem_config.h> 

#include <stdio.h> 
#include "testdll.h" 

using namespace android; 
extern "C" { 
    int TestClass::max(int x,int y){ 
     return x>y?x:y; 
    } 
} 

testdll.h:

using namespace android; 

class TestClass 
{ 
    public: 
     int max(int, int); 
}; 

main.h:

#include <stdio.h> 
#include <dlfcn.h> 
#include <stdlib.h> 

typedef int (*test_ptr)(int, int); 

int main() 
{ 
    int rc; 
    void *handle; 
    const char *error; 

    handle = dlopen("./testdll.so", RTLD_LAZY); 
    if(!handle){ 
     printf("dlopen %s\n", dlerror()); 
     return -1; 
    } 
    printf("dlopen success.\n"); 

    test_ptr test = (test_ptr)dlsym(handle, "max"); 
    error = dlerror(); 
    if (error) { 
     printf("error %s\n", error); 
     dlclose(handle); 
     return -1; 
    } 
    rc = test(10, 20); 
    printf("rc = %d\n", rc); 

    dlclose(handle); 
    return 1; 
} 

然後我得到了相同的錯誤消息:找不到符號:

我用objdump的-TC顯示:

DYNAMIC SYMBOL TABLE: 
000003f5 g DF .text 0000000a TestClass::max(int, int) 
00000000  DF *UND* 00000000 __aeabi_unwind_cpp_pr0 
00000000  DF *UND* 00000000 __cxa_finalize 
000010f0 g D .bss 00000000 __dso_handle 
00001000 g D .init_array 00000000 __INIT_ARRAY__ 
00001008 g D .fini_array 00000000 __FINI_ARRAY__ 
00000410 g D *ABS* 00000000 __exidx_end 
00000400 g D *ABS* 00000000 __exidx_start 
000010ec g D *ABS* 00000000 __data_start 
000010ec g D *ABS* 00000000 _edata 
000010ec g D *ABS* 00000000 __bss_start 
000010ec g D *ABS* 00000000 __bss_start__ 
00001100 g D *ABS* 00000000 _bss_end__ 
00001100 g D *ABS* 00000000 __bss_end__ 
00001100 g D *ABS* 00000000 __end__ 
00001100 g D *ABS* 00000000 _end 
00080000 g D *ABS* 00000000 _stack 

如何修改?

再次感謝!

+0

,你可能需要添加__declspec(dllexport)的在MAX()的前出口的符號,即: -__ declspec(dllexport)int max(int x,int y){..},檢查此問題以查看所有導出的符號http://stackoverflow.com/questions/34732/how-do-i-list-the- symbols-in-a-so-file – 2012-07-12 02:05:32

+0

雖然你的問題似乎是名稱混亂,但你應該首先檢查dlsym()的返回值,然後再檢查dlerror()。 – 2012-07-12 03:02:59

回答

2

你的符號表中的TestClass :: max(int,int) - 這是否意味着你最大的功能是一個類的方法?

嘛,如果是的話,你需要創建一個C換到你的TestClass,例如

extern "C" 
{ 
    int max (void *pHandle, int x, int y) 
    { 
     TestClass *tcObject = (TestClass *)pHandle; 
     return tcObject->max(x, y); 
    } 
} 
+0

+1通過這樣一個大的帖子,並回答它.. :) – 2012-07-13 10:47:51

1

您計劃通過dlopen訪問的任何函數必須聲明爲extern "C"。原因是name mangling

+0

這不是真的,你需要使用'extern「C」'。實際上,您必須使用該名稱,因爲它在外部模塊中是已知的,不一定在源代碼中知道它的名稱。 * easy *方法是'extern「C」'這樣兩個名稱都是相同的,但並不是絕對必要的。如果需要,可以使用重名的名稱導入。 – 2012-07-12 02:48:55

+0

是的,它可以通過重名名稱導入,但是重名名稱必須傳遞給dlsym()。另一方面,如果一個可執行文件是以硬編碼方式依賴庫生成的,那麼可能會自動處理這個可執行文件,因爲不會手動調用dlsym()。 – 2012-07-12 03:02:09

+0

謝謝,它的工作!現在我想用C++編寫,並得到相同的錯誤消息。 – Tony 2012-07-12 03:57:26

相關問題