2017-07-17 71 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*/ 
    } 
} 

希望我已经回答了你的问题。