动态使用共享库函数

dll_main   

 

环境介绍

续上节代码

目录结构:

 

android.mk如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := demo

LOCAL_SRC_FILES := mod1.cpp mod2.cpp mod3.cpp

include $(BUILD_SHARED_LIBRARY)

include $(CLEAR_VARS)

LOCAL_MODULE    := Hello

LOCAL_SRC_FILES := Hello.cpp

include $(BUILD_EXECUTABLE)

 

Hello.cpp

#include <stdio.h>

#include <dlfcn.h>

typedef void (*FUNTYPE)();

int main(int argc, char* argv[])

{

    //加载共享库

    void *handle = dlopen("/data/local/tmp/libdemo.so", RTLD_NOW);

    if (handle == NULL)

    {

        puts(dlerror());

        return 0;

    }

    printf("handle=%p\n", handle);

    //获取导出函数

    FUNTYPE pfnMod = (FUNTYPE)dlsym(handle, "_Z4mod1v");

    if (pfnMod != NULL)

    {

        printf("address=%p\n", pfnMod);

        pfnMod();

    }

    pfnMod = (FUNTYPE)dlsym(handle, "_Z4mod2v");

    if (pfnMod != NULL)

    {

        printf("address=%p\n", pfnMod);

        pfnMod();

    }

    pfnMod = (FUNTYPE)dlsym(handle, "_Z4mod3v");

    if (pfnMod != NULL)

    {

        printf("address=%p\n", pfnMod);

        pfnMod();

    }

    pfnMod = (FUNTYPE)dlsym(handle, "mod4");

    if (pfnMod == NULL)

    {

        puts(dlerror());

    }

    dlclose(handle);

    return 0;

}

 

_Z4mod2v 是C++的名称粉碎

函数名可以用readelf来进行查看:

该工具在: E:\Android\android-ndk-r10b\toolchains\x86-4.6\prebuilt\windows-x86_64\bin\i686-linux-android-readelf.exe

 

 

类似于Windows动态调用dll的思想

dlopen打开一个so文件

dlsym根据函数名拿到函数指针

 

编译后使用makefile执行

在工程目录根下新建makefile:

MODALE_NAME := Hello

# x86 path

X86_TOOLS_PATH :=E:\Android\android-ndk-r10b\toolchains\x86-4.6\prebuilt\windows-x86_64\bin

X86_GDB_PATH := $(X86_TOOLS_PATH)\i686-linux-android-gdb.exe

X86_GDB_SERVER := E:\Android\android-ndk-r10b\prebuilt\android-x86\gdbserver\gdbserver

# arm-linux-androideabi-4.6 path

arm_tools_path :=E:\Android\android-ndk-r10b\toolchains\arm-linux-androideabi-4.6\prebuilt\windows-x86_64\bin

arm_4_6_path := $(arm_tools_path)\arm-linux-androideabi-gdb.exe

arm_gdb_server :=E:\Android\android-ndk-r10b\prebuilt\android-arm\gdbserver\gdbserver

run_arm:

    adb push .\libs\armeabi-v7a\$(MODALE_NAME) /data/local/tmp

    adb shell chmod 755 /data/local/tmp/$(MODALE_NAME)

    adb shell /data/local/tmp/$(MODALE_NAME)

run_x86:

    adb push .\libs\x86\$(MODALE_NAME) /data/local/tmp

    adb shell chmod 755 /data/local/tmp/$(MODALE_NAME)

    adb shell /data/local/tmp/$(MODALE_NAME)

run_x86_share:

    adb push .\libs\x86\$(MODALE_NAME) /data/local/tmp

    adb push .\libs\x86\libdemo.so /data/local/tmp

    adb shell chmod 755 /data/local/tmp/$(MODALE_NAME)

    adb shell /data/local/tmp/$(MODALE_NAME)

debug_x86:

    adb forward tcp:12345 tcp:12345

    adb push $(X86_GDB_SERVER) /data/local/tmp

    adb shell chmod 777 /data/local/tmp/gdbserver

    adb push .\obj\local\x86\$(MODALE_NAME) /data/local/tmp

    adb shell chmod 777 /data/local/tmp/$(MODALE_NAME)

    adb shell /data/local/tmp/gdbserver :12345  /data/local/tmp/$(MODALE_NAME)

client_x86:

    $(X86_GDB_PATH) .\obj\local\x86\$(MODALE_NAME)

# 1. target remote localhost:12345

# 2. gdb.setup  

 

 

make run_x86_share 即可成功执行

mod4 会提示找不到

 

 

DLL_MAIN

修改mod1.cpp

#include <stdio.h>

// 初始化函数

void   _init()

{

  printf("_init\r\n");

}

// so卸载函数

void   _fini()

{

  printf("_fini\r\n");

}

// 新版本初始化函数

void __attribute__((constructor))  OnLoad()

{

  printf("OnLoad\r\n");

}

void __attribute__((destructor))  UnLoad()

{

  printf("UnLoad\r\n");

}

void __attribute__((constructor))  OnLoad2()

{

  printf("OnLoad2\r\n");

}

void __attribute__((destructor))  UnLoad2()

{

  printf("UnLoad2\r\n");

}

//隐藏函数

void __attribute__((visibility("hidden")))  mod1()

{

  printf("mod1\r\n");

}

 

运行效果:

说明:

1. _init函数比构造函数来的早

2. hidden后在用dlsym函数无法找到

 

总结

1.相关函数

dlopen()函数打开一个共享库

dlsym()函数在库中搜索一个符号

dlclose() 函数光比之前dlopen打开的库

dlerror() 函数返回一个错误消息的字符串

 

2.隐藏函数

Void __attribute__ ((visibility("hidden"))) fun() {}

 

3. so构造析构(会在so加载和卸载的时候调用)

   void  __attribute__ ((constructor)) Load()

   void  __attribute__ ((destructor)) UnLoad()

 

4. _init()和_fini()函数

会在so加载和卸载时调用

 

 

 

ndk学习9: 动态使用共享库的更多相关文章

  1. Android NDK 交叉编译C++代码生成.so共享库详细步骤

    Android NDK 交叉编译C++代码生成.so共享库详细步骤 Android NDK 调用c++ stl 模板库(修改android.mk文件) 1  在需要调用模板库的文件前包含头文件:   ...

  2. Android JNI和NDK学习(03)--动态方式实现JNI(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092491.html 前面总结了静态实现JNI的方法,本文介绍如何动态实现J ...

  3. Linux学习笔记——如何使用共享库交叉编译

    0.前言     在较为复杂的项目中会利用到交叉编译得到的共享库(*.so文件).在这样的情况下便会产生下面疑问,比如:     [1]交叉编译时的共享库是否须要放置于目标板中,假设须要放置在哪个文件 ...

  4. Android NDK生成共享库和静态库

    Date: 2014-03-14 Title: Compile Android Native Binary And Library Published: true Type: post Tags: A ...

  5. Android JNI和NDK学习(04)--NDK调试方法(转)

    本文转自:http://www.cnblogs.com/skywang12345/archive/2013/05/23/3092812.html 本文主要介绍在ndk中添加log的方法.然后,我们就可 ...

  6. ndk学习8: 编译动态库

    目录: 手工编译动态库 ndk-build编译动态库(Eclipse环境)   手工编译静态库 老规矩还是先手工操作,知其然并知其所以然   需要用到的核心命令: gcc -g -c -fpic -W ...

  7. 《CMake实践》笔记三:构建静态库(.a) 与 动态库(.so) 及 如何使用外部共享库和头文件

    <CMake实践>笔记一:PROJECT/MESSAGE/ADD_EXECUTABLE <CMake实践>笔记二:INSTALL/CMAKE_INSTALL_PREFIX &l ...

  8. ndk学习20: jni之OnLoad动态注册函数

    一.原理 当在系统中调用System.loadLibrary函数时,该函数会找到对应的动态库, 然后首先试图找到"JNI_OnLoad"函数,如果该函数存在,则调用它 JNI_On ...

  9. Linux共享库、静态库、动态库详解

    1. 介绍 使用GNU的工具我们如何在Linux下创建自己的程序函数库?一个“程序函数库”简单的说就是一个文件包含了一些编译好的代码和数据,这些编译好的代码和数据可以在事后供其他的程序使用.程序函数库 ...

随机推荐

  1. LVS相关学习

    vi /etc/sysctl.conf net.ipv4.conf.eth0.arp_ignore = 1 net.ipv4.conf.eth0.arp_announce = 2 net.ipv4.c ...

  2. FreeImage使用

    http://blog.csdn.net/byxdaz/article/details/6056509 http://blog.chinaunix.net/uid-20660110-id-65639. ...

  3. 服务器后台TCP连接存活问题

    0. 背景 公司的服务器后台部署在某一个地方,接入的是用户的APP,而该地方的网络信号较差,导致了服务器后台在运行一段时间后用户无法接入,那边的同事反馈使用netstat查看系统,存在较多的TCP连接 ...

  4. linux下google chrome浏览器字体修改

    今天安装了最新的chrome,我是下载的.deb包直接安装的. 安装完后,用chrome浏览页面时,发现字体有的大,有的小,还不清楚. 于是在网上搜索了一下如何设置字体. 1.打开Chrome浏览器. ...

  5. 安装windows后重新修复grub2的引导

    前段时间,我的用的双系统windows8.1 + fedora 21 workstation,使用grub2引导fedora和windows8.1的启动.由于一些原因,导致我的windows8.1无法 ...

  6. 利用afxDump来调试自己的程序

    http://blog.csdn.net/sstower/article/details/7714199

  7. Myeclipse如何关联源码

    Myeclipse版本:Myeclipse2014 关联源码前要下载对应的源码,如本例的dom4j-1.6.1.jar,则去下载对应的源码dom4j-1.6.1.zip 如果做的是web项目,就要将该 ...

  8. Apache服务器httpd.exe进程占用cpu超过50%的解决方法

    httpd.exe进程占用cpu超过50%,关闭掉Apache服务,cpu应用率立刻下降到0.  重新启动Apache又出现占用cpu高的情况.  原因是:httpd.exe和防火墙配置有冲突. 解决 ...

  9. 自己总结的USB数据结构及其描述符

    背景: USB理论知识光看着空想总觉着丢三落四,好像哪里没法理解到位,自己做个总结. 正文: 1. USB通信的最基本单位是“包”.如果把“包”肢解的话,可以分为各种“域”(7类,即一串二进制数.每类 ...

  10. WP8微信5.3开始内测 支持Cortana语音 两微破冰了?

    WP版微信v5.3内测版昨发布了,进行了一些小幅升级,最意外的是原生支持WP8.1版Cortana语音命令操作.要知道微软的聊天机器人“小冰”在微信上存在不到4天,就被微信全面封杀退出,现在微信又内测 ...