2017-07-17 72 views
1

在我的項目中,我正在實現一個JNI代理,它將在我的自定義「.c」文件中將所有java原生方法重新綁定到我的自定義方法中。因此,由於JNI代理在運行時綁定本地方法,因此我只會談論運行時解決方案。C獲取函數地址

當JNI結合本地方法,下面的函數被調用:

void JNICALL NativeMethodBind(jvmtiEnv *jvmti_env, 
    JNIEnv* jni_env, 
    jthread thread, 
    jmethodID method, 
    void* address, 
    void** new_address_ptr) 

此時Java方法獲取綁定,除非你把東西放到void** new_address_ptr解決void* address。因此,爲了重新綁定窗簾方法,我只需要覆蓋new_address_ptr - 變量。

現在,我想重新將函數重新綁定到包含數百種不同方法的自定義.c文件中的函數地址。這就是我卡住的地方。雖然具有.c文件和函數的字符串名稱,但我如何獲取我的.c文件中相應函數的地址?

我運行windows64機器上的項目用gcc 4.9.1

+0

您有* * .c'文件中存在的函數的字符串名稱有多大可能? – Gaurav

+0

@GauravPathak @GauravPathak很有可能,就像它是100%肯定有... –

+0

在c代碼中,函數名稱也是它的地址,在程序集中添加「_」作爲前綴。 – sdao

回答

1

這是你需要的嗎?

#include <stdio.h> 

#define MAX_FN 1024 
#define SYMBOL_ENTRY(i, name) do { \ 
     _fn_table[i].fn_name = #name; \ 
     _fn_table[i].fn_addr = &name; \ 
} while(0) 

struct fn_table { 
     const char *fn_name; 
     void *fn_addr; 
}; 

static struct fn_table _fn_table[MAX_FN] = { }; 

static void test0(void) { 
     printf("%s [%d]\n", __func__, __LINE__); 
} 

static void test1(int a) { 
     printf("%s [%d] %d\n", __func__, __LINE__, a); 
} 

static struct fn_table _fn_table_statically_initialization[] = { 
     { "test0", &test0 }, 
     { "test1", &test1 } 
}; 


int main(int argc, char *argv[]) { 
     // build table 
     SYMBOL_ENTRY(0, test0); 
     SYMBOL_ENTRY(1, test1); 

     // let's print out 
     printf("%p\n", _fn_table[0].fn_addr); 
     printf("%p\n", _fn_table[1].fn_addr); 
     printf("%p\n", _fn_table_statically_initialization[0].fn_addr); 

     // try to call 
     if (_fn_table[0].fn_addr) { 
       void (*fn)(void) = _fn_table[0].fn_addr; 

       fn(); 
     } 

     if (_fn_table[1].fn_addr) { 
       void (*fn)(int) = _fn_table[1].fn_addr; 

       fn(12); 
     } 

     return 0; 
} 
+0

無效的從'void(*)(int)'轉換爲'void *'[-fpermissive],在數組初始化....我需要把-fpermissive放在什麼地方? –

+0

好的,編輯過的,屁股'&'來取代函數地址'_fn_table [i] .fn_addr = &name;' – sdao

2

你所想達到可使用的結構,如果你可以編輯自定義*.c文件,那麼你可以有兩個成員的結構來完成像:

struct func_details{ 
    char func_name[20]; 
    void (*custom_func)(void); 
}; 

然後聲明結構數組:

struct func_details my_functions[] = { 
     {"function1 name as string", respective_func1} 
     {"function2 name as string", respective_func2} 
     {"function3 name as string", respective_func3} 
}; 

現在你可以在一個循環L做了strcmp() ike

for(i=0; i<3; i++) 
{ 
    if(strcmp(function_string, my_functions[i].func_name) == 0) 
    { 
     if(my_functions[i].custom_func != NULL) 
      /*Call you method to update the address with my_functions[i].custom_func*/ 
    } 
} 

希望我已經回答了你的問題。