记录生成.so库的步骤,以防自己每次忘记。用的是eclipse。

一、先在eclipse中生成一个android工程,然后在android工程下的src新建一个package,例如名字为com.android.aa,在其下新建一个java文件,这个文件相当于与.so库的一个对接接口,其形式为:

package com.android.aa;

public class NativeAA{

static{

System.loadLibrary("aa"); //加载aa.so库

}

public native byte[] sent(String input); //调用so库中的sent函数

}

保存一下,就可以在./bin/classes/com/android/aa文件下生成NativeAA.class文件。


二、利用javah生成jni的头文件

首先利用cmd进入目录中:例如工程放在了F盘,工程为test:

f: //这是进入了f盘

cd ./test/bin/classes目录下,运行下一命令:

javah com.android.aa.NativeAA

就会在classes生成了一个com_android_aa_NativeAA.h的头文件

里面就是一个函数的声明:

JNIEXPORT jbyteArray JNICALL Java_com_android_aa_NativeAA_sent

(jnienv*,jobject,jstring);(其他的省略,并且java中有几个函数声明,.h就对应生成几个,我这里是一个)

三、生成与.h对应的.cpp文件

在Ubuntu中建立一个文件夹,例如:我在project的文件下建立了一个aa的文件下,然后建立一个jni文件下,将com_android_aa_NativeAA.h方进去,再新建一个对应的.cpp

,在命令窗口输入geditcom_android_aa_NativeAA.cpp,就建立以个.cpp文件。再建立实现sent函数的.cpp和.h这里命名为sent.cpp和sent.h。

sent.cpp的中的函数sent实现的是输入为char*,输出的参数为char*类型,其声明为:

int sent(char* sentInput,char **sentInput);

char*sentInput是输入,char**sentInput是输出(实际需要的是char*,返回二级指针下面会说明),返回int是标志位,这个程序运行下来返回0表示成功;其他值表示失败。

com_android_aa_NativeAA.cpp的形式:

#include "com_android_aa_NativeAA.h"

#define TAG "so-jni"

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__) //

//功能:实现将jstring转换为char*

char*jstringTostring(jnienv*env,jstring jstr);

JNIEXPORT jbyteArray JNICALL Java_com_android_aa_NativeAA_sent

(jnienv*env,jobject object,jstring jinput) //jstring jinput对应的是java文件中的String input

{

//首先将jstring转成char类型,因为我的例程中sent.cpp中的函数的输入参数是char*;

char *inputChar=jstringTostring(env,jinput);

if(inputChar==NULL)

{

LOGD("jstring转换char失败!")

return NULL;

}

else

{

char *outData=new char[255];

memset(outData,255);

if(outData==NULL)

return NULL;

int ret=sentInput(InputChar,&outData); //outData是返回值,&outData这样做是返回一组数组。

if(ret==0)

{

//这是将c++中的char*转为为java中的byte[];

jbyte *joutData=(jbyte*)outData;

jbyteArray jarrOutData=env->NewByteArray(255);

env->SetByteArrayRegion(jarrOutData,255,joutData);

delete[ ] outData;

return jarrOutData;

}

else

{

delete[] outData;

return NULL;

}

}

delete[ ] inputData;

}

//将Java中的String转换为c++中的char*

char*jstringTostring(jnienv* env,jstring jstr)

{

char*ttn=NULL;

jclass clsstring=env->env->FindClass("java/lang/string");

jstring strInput=env->NewStringUTF("utf-8");

jmethodID mid=env->getmethodID(clsstring,"getBytes","(Ljava/lang/String;)[B");

jbyteArray barr=(jbyteArray)env->CallObjectMethod(jstr,mid,strencode);

jsize alen=env->GetArrayLength(barr);

jbyte*ba=env->GetByteArrayElements(barr,JNI_FALSE);

if(alen>0)

{

rtn=(char*)malloc(alen+1);

memcpy(rtn,ba,alen);

rtn[alen]=0;

}

env->ReleaseByteArrayElements(barr,0);

return rtn;

}

四、两个makefile文件

(1)Application.mk:用于描述APP需要的native model

其内容为:

APP_PLATFORM :=android-19

APP_STL :=gnustl_static #要使用到的标准c++库

APP_CPPFLAGS :=-frtti -fexceptions

APP_ABI :=armeabin

分析:

Application.mk常用的有四个:

a. APP_PLATFORM :=android-19

表示使用ndk库函数版本号。一般和SDK的版本相对应,各个版本在NDK目录下的platforms文件夹中

b. APP_STL :=stlport_static

定义NDK的编译系统的运行时库,有如下几种:

system:默认最小的c++运行库,生成的应用体积小,内存占用少,但部分功能将无法支持

stIport_static:使用STLport作为静态库(推荐使用)

stlport_shared:STLport作为动态库(不推荐,可能产生兼容性和部分低版本的Android固件)

gnustl_static:使用GNU libstdc++作为静态库

c. APP_ABI:=armeabi

表示要编译成对应指令集cpu的动态库,armeabi:ARMv7指令集,armeabi-v7a:ARMv7+硬件FPU指令集,x86:IA-32指令集,all支持常用的指令集

d. APP_CPPFLAGS:该变量列出了一些编译器标志,在便以任何模块的c++代码时这些标志都会被传给编译器;

e. APP_OPTIM:=debug(我自己的项目没用这一项)

设置编译类型,debug:调试版本,so动态库中带调试信息(可以使用gdb-server尽心动态段断点低调试),release:发布版本,so库不带调试信息

(2)Android.mk:用于描述构建系统的源文件以及shareed libraries。

其内容:

LOCAL_PATH :=&(call my-dir)

APP_STL :=gnustl_static #要用到标准c++库,如果不用可以注释掉

include $(CLEAR_VARS)

LOCAL_LDLIBS:=-llog

LOCAL_MODULE :=aa #aa为行程so库的库名

LOCAL_SRC_FILES :=sent.cpp \

com_android_usbkey_NativeUsbBase.cpp \

LOCAL_CFLAGS :=-arm -mfloat-abi=softfp -mfpu=vfp -Wmultichar

include $(BUILD_SHARED_LIBRARY)

总结:

要行程.so库的流程就这些(可根据自己的情况添加.cpp),需注意的是:ubuntu上必须安装ndk上述文件才可以形成.so库。

在命令窗口需输入的:

1.首先进入jni文件所在的目录(删除的文件都放在jni文件里);

2.输入命令:ndk-build即可生成so库(注意:清楚so库的命令为:ndk-build clean)

利用Ubuntu将c++文件生成.so库的更多相关文章

  1. 为什么这个OpenGL ES 2.0着色器不能在iOS上使用我的VBO?

    如果有人能够了解这里出了什么问题,也许是对gl命令或其他一些不兼容的命令序列的错误排序,我将非常感谢你的帮助.尽管谷歌在“OpenGLES2.0编程指南”中进行了大量研究和研究,但我一直试图让这段代码整天都没有成功.我正在尝试在iPhone上的OpenGLES2.0中使用顶点缓冲区对象和自定义着色器.我试图交错来自以下类型的一系列自定义结构的顶点数据:位置,半径和颜色字节分别考虑顶点位置,点大小和

  2. ios – 将两个字符串转换为一组布尔值的快速方法是什么?

    我有一个长字符串,我想转换为一个布尔值数组.而且它需要很多次,很快.我天真的尝试是这样的:但这比我想要的要慢很多.我的剖析告诉我,地图是减速的地方,但我不知道我能做多么简单.我觉得如果没有Swift’s/ObjC的开销,这样做会很快.在C中,我认为这是一个简单的循环,其中一个字节的内存与一个常量进行比较,但我不知道我应该看的是什么函数或语法.有更好的办法吗?

  3. 在iOS上默认是char签名还是未签名?

    默认情况下,iOS上是否签名或未签名?(我认为这将是一个很好的回答问题,但奇怪的是谷歌没有任何用处!

  4. ios – 如何创建一个本机显示浮动窗口的ANE

    如何在Xcode中创建本机窗口并将其与MobileFlex应用程序集成.本机窗口应该与StageWebView组件类似,其中本机内容浮动在Flex应用程序的其余部分的矩形区域中.解决方法作为一名灵活的程序员,这是一个繁琐的过程,花了我几个星期才弄明白.希望这将有助于其他一些Xcode新手.首先,您必须对Objective-C和Xcode有基本的了解.您应该能够创建一个简单的HelloWorldXc

  5. Swift基础-0003

  6. Swift语言和其他计算机语言的比较

    Swift集成了传统面向对象编程语言的特性,同时又具备函数式编程的一些特征。在2014年WWDC之前,用来开发iOS应用的语言被称为Objective-C,它是标准C语言的扩展。使用Objective-C可以完成C语言所能完成的任何工作。这里不得不提到C++语言,事实上C++和Objective-C语言几乎是同时出现的。和Objective-C语言的简洁不同,C++语言几乎包含了所有可能的特性。

  7. Swift Name Mangling - Swift语言的名字重整技术

    在比如C这样的语言中,任何给定的名字(符号)只能对应唯一的一个函数或数据,不需要名字重整。因此,c++编译器使用一组严格的编码规则“mangles”(重整)了符号。想获取更多的关于经典C++编译器重整名字的内容,请参考ItaniumC++ABIdocumentation.总结:Object-C类似于C语言,Swift类似于C++,有函数重载,有虚函数表,需要命名重整。

  8. Swift中如何转换不同类型的Mutable指针

    在Swift中我们拥有强大高级逻辑抽象能力的同时,低级底层操作被刻意的限制了.但是有些情况下我们仍然想做一些在C语言中的hack工作,下面本猫就带大家看一看如何做这样的事.hackingishappy!!!如上代码我们只要在闭包中返回一个Char指针就可以了,怎么做呢?这就需要借助另一个超级强大的方法unsafeBitCast,该方法将一种类型的变量内容强制转换为另一种,将以上闭包的//???这里不予解释,因为常玩汇编或C的小伙伴肯定早就了然于心鸟!

  9. 你是如何评价Swift的,谈谈你的感受!

    假如之前已经掌握了Objective-C,切换到Swift也不难。Swift还没有很好地解决好跟C和C++混编的问题。随着时间推移,Swift在整个iOS/Mac工程中占的代码比例会越来越多,而Objective-C作为粘合层还是会存在。只是等你真正使用Swift编写一两个项目,就回不了头。Swift有些简便快速的写法,在Objective-C中是没有办法做到的。并且Swift的一些语言特性避免了很多Objective-C的坑。使用Swift编写的任何功能,使用Objective-C也可以做到,但是会麻烦

  10. Mastering Swift: essential details about strings

    https://rainsoft.io/mastering-swift-essential-details-about-strings/MasteringSwift:essentialdetailsaboutstringsDmitriPavlutin|05Oct2016Stringtypeisanimportantcomponentofanyprogramminglanguage.Themostu

随机推荐

  1. crontab发送一个月份的电子邮件

    ubuntu14.04邮件服务器:Postfixroot收到来自crontab的十几封电子邮件.这些邮件包含PHP警告.>我已经解决了这些警告的原因.>我已修复每个cronjobs不发送电子邮件(输出发送到>/dev/null2>&1)>我删除了之前的所有电子邮件/var/mail/root/var/spool/mail/root但我仍然每小时收到十几封电子邮件.这些电子邮件来自cronjobs,

  2. 模拟两个ubuntu服务器计算机之间的慢速连接

    我想模拟以下场景:假设我有4台ubuntu服务器机器A,B,C和D.我想在机器A和机器C之间减少20%的网络带宽,在A和B之间减少10%.使用网络模拟/限制工具来做到这一点?

  3. ubuntu-12.04 – 如何在ubuntu 12.04中卸载从源安装的redis?

    我从源代码在Ubuntu12.04上安装了redis-server.但在某些时候它无法完全安装,最后一次makeinstallcmd失败.然后我刚刚通过apt包安装.现在我很困惑哪个安装正在运行哪个conf文件?实际上我想卸载/删除通过源安装的所有内容,只是想安装一个包.转到源代码树并尝试以下命令:如果这不起作用,您可以列出软件自行安装所需的步骤:

  4. ubuntu – “apt-get source”无法找到包但“apt-get install”和“apt-get cache”可以找到它

    我正在尝试下载软件包的源代码,但是当我运行时它无法找到.但是当我运行apt-cache搜索squid3时,它会找到它.它也适用于apt-getinstallsquid3.我使用的是Ubuntu11.04服务器,这是我的/etc/apt/sources.list我已经多次更新了.我尝试了很多不同的debs,并没有发现任何其他地方的错误.这里的问题是你的二进制包(deb)与你的源包(deb-src)不

  5. ubuntu – 有没有办法检测nginx何时完成正常关闭?

    &&touchrestarted),因为即使Nginx没有完成其关闭,touch命令也会立即执行.有没有好办法呢?这样的事情怎么样?因此,pgrep将查找任何Nginx进程,而while循环将让它坐在那里直到它们全部消失.你可以改变一些有用的东西,比如睡1;/etc/init.d/Nginx停止,以便它会休眠一秒钟,然后尝试使用init.d脚本停止Nginx.你也可以在某处放置一个计数器,这样你就可以在需要太长时间时发出轰击信号.

  6. ubuntu – 如何将所有外发电子邮件从postfix重定向到单个地址进行测试

    我正在为基于Web的应用程序设置测试服务器,该应用程序发送一些电子邮件通知.有时候测试是使用真实的客户数据进行的,因此我需要保证服务器在我们测试时无法向真实客户发送电子邮件.我想要的是配置postfix,以便它接收任何外发电子邮件并将其重定向到一个电子邮件地址,而不是传递到真正的目的地.我正在运行ubuntu服务器9.10.先感谢您设置本地用户以接收所有被困邮件:你需要在main.cf中添加:然后

  7. ubuntu – vagrant无法连接到虚拟框

    当我使用基本的Vagrantfile,只配置了两条线:我看到我的虚拟框打开,但是我的流氓日志多次显示此行直到超时:然后,超时后的一段时间,虚拟框框终于要求我登录,但是太久了!所以我用流氓/流氓记录.然后在我的物理机器上,如果我“流氓ssh”.没有事情发生,直到:怎么了?

  8. ubuntu – Nginx – 转发HTTP AUTH – 用户?

    我和Nginx和Jenkins有些麻烦.我尝试使用Nginx作为Jenkins实例的反向代理,使用HTTP基本身份验证.它到目前为止工作,但我不知道如何传递带有AUTH用户名的标头?}尝试将此指令添加到您的位置块

  9. Debian / Ubuntu – 删除后如何恢复/ var / cache / apt结构?

    我在ubuntu服务器上的空间不足,所以我做了这个命令以节省空间但是现在在尝试使用apt时,我会收到以下错误:等等显然我删除了一些目录结构.有没有办法做apt-getrebuild-var-tree或类似的?

  10. 检查ubuntu上安装的rubygems版本?

    如何查看我的ubuntu盒子上安装的rubygems版本?只是一个想法,列出已安装的软件包和grep为ruby或宝石或其他:)dpkg–get-selections

返回
顶部