〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)

一、背景:假定已有应用程序zigbeeclient.cpp,内容如下:

〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)
...
extern "C" {
    int getresult(int argc, char **argv);
}

int getresult(int argc, char **argv)
{ 
    ...
}
〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)

  这个文件生成一个动态链接库libzigbee.so

$(CXX) $(CXXFLAGS) $(MYCLIENTCFLAGS) $(LDFALGS) $(INCLUDE) -fPIC -llog -shared $^ -o libzigbee.so

二、期望:能在Android任意一个的NDK应用程序中,可调用此库中的getresult()函数

  1. 编写NDK的C语言文件zigbeeclient.c,内容如下:

〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <jni.h>

/*-----------------------------------------------------------------------------
 *  从libzigbee.so中调用进来的函数
 *-----------------------------------------------------------------------------*/
int getresult(int argc, char **argv);

/*-----------------------------------------------------------------------------
 *  String to char*
 *-----------------------------------------------------------------------------*/
char* jstring_to_pchar(JNIEnv* env, jstring str)
{
    char* pstr = NULL;
    jclass clsstring = (*env)->FindClass(env, "java/lang/String");
    jstring strencode = (*env)->NewStringUTF(env, "utf-8");
    jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes",
                "(Ljava/lang/String;)[B");
    jbyteArray byteArray = (jbyteArray)(
                (*env)->CallObjectMethod(env, str, mid, strencode));
    jsize size = (*env)->GetArrayLength(env, byteArray);
    jbyte* pbyte = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);
    if (size > 0)
    {
        pstr = (char*) malloc(size);
        memcpy(pstr, pbyte, size);
    }
    return pstr;
}

jstring
Java_com_scue_zigbeeclient_ZigbeeActivity_getResultJni( JNIEnv* env, jobject thiz ,
        jstring subdev, jstring ctrltype, jstring mod, jstring server)
{
    int ret=0;
    int argc = 4;
    char *argv[4];
    argv[0]=jstring_to_pchar(env, subdev);
    argv[1]=jstring_to_pchar(env, ctrltype);
    argv[2]=jstring_to_pchar(env, mod);
    argv[3]=jstring_to_pchar(env, server);
    ret = getresult(argc, argv);
    char cret[10]="";
    sprintf(cret, "%d", ret);
    return (*env)->NewStringUTF(env, cret);
}
〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)

  2. 编写Android.mk文件:

〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := zigbee-prebult
LOCAL_SRC_FILES := libs/libzigbee.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
LOCAL_SHARED_LIBRARIES := zigbee-prebult
include $(BUILD_SHARED_LIBRARY)
〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)

  3. 在Java程序文件中,load动态库的顺序有讲究(后一个依赖于前一个):

public native String  getResultJni(String subdev, String ctrltype, String mod, String server);
static {
    System.loadLibrary("zigbee");
    System.loadLibrary("zigbeeclient");        
}

  4. 其他的细节可以下载我打包好的tar文件:Android_NDK_Extra_So.tgz

〖Linux〗Android NDK调用已编译好的C/C++动态连接库(so文件)

上一篇:〖Linux〗VIM youcompleteme 自动补全 #include 文件名称


下一篇:C++获取appdata路径