Android NDK编程浅入深出之--Android.mk
Android.mk
Android.mk是一个向Android NDK构建系统描写叙述NDK项目的GUN Makefile片段。它是每个NDK项目的必备组件。
构建系统希望它出如今jni子文件夹中。
以下是hello-jni项目中Android.mk文件的内容。
- # 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 := hello-jni
- LOCAL_SRC_FILES := hello-jni.c
- include $(BUILD_SHARED_LIBRARY)
为了更好地理解它的句法。我们逐行分析。由于这个是一个GUN Makefile片段,所以它的句法和其它Makefile是一样的。每行都包括一个单独的指令,以“#”开头的是凝视行,GUN Make 工具不处理它们。依据命名规范。变量名要大写。
凝视块后的第一条指令是用来定义LOCAL_PATH变量的。依据Android构建系统的要求,Android.mk文档必须以LOCAL_PATH变量的定义开头。
- LOCAL_PATH :=$(call my-dir)
Android构建系统利用LOCAL_PATH来定位源文件。由于将该变量设置为硬编码值并不合适,所以Android构建系统提供了一个名为my-dir的宏功能。
通过将该变量设置为my-dir 宏功能的返回值,能够将其放在当前文件夹下。
Android构建系统将CLEAR_VARS变量设置为clear-vars.mk片段的位置。
包括Makefile片段能够清除除了LOCAL_PATH以外的LOCAL_变量,比如LOCAL_MODULE与LOCAL_SRC_FILES等。
- Include $(CLEAR_VARS)
这样做是由于Android构建系统在单次运行中解析多个构建文件和模块定义。而LOCAL_是全局变量。清除它们能够避免冲突,每个原生组件被称为一个模块。
LOCAL_MODULE变量用来给这些模块设定一个唯一的名称。以下的代码将该模块的名称设为hello-jni:
- LOCAL_MODULE := hello-jni
由于模块名称也被用于给构建过程所生成的文件命名,所以构建系统给该文件加入了适当的前缀和后缀。本例中,hello-jni模块会生成一个共享库文件且构建系统会将它命名为libhello-jni.so。
用LOCAL_SRC_FILES变量定义用来建立和组装这个模块的源文件列表。
- LOCAL_SRC_FILES := hello-jni.c
这里,hello-jni模块仅仅由一个源文件生成,而LOCAL_SRC_FILES变量能够包括用空格分开的多个源文件名称。
至此,Android.mk文件里定义的构建系统变量简单描写叙述了原生项目。
编译和生成实际模块的构建系统还须要包括合适的构建系统片段,详细须要包括哪些片段取决于想要生成模块的类型。
1. 构建共享库
为了建立可供主应用程序使用的模块。必须将该模块变成共享库。Android NDK构建系统将BUILD_SHARED_LIBRARY变量设置成build-shared-library.mk文件的保存位置。该Makefile片段包括了将源文件构建和组装成共享库的必要过程:
- include $(BUILD_SHARED_LIBRARY)
hello-jni是一个简单的模块;然而。除非你的模块须要特殊处理,否则Android.mk文档将会包括一模一样的流程和指令。
2. 构建多个共享库
基于不同的应用程序的体系结构,一个单独的Android.mk文档可能产生多个共享库模块。如程序:
- LOCAL_PATH := $(call my-dir)
- #
- #模块 1
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module1
- LOCAL_SRC_FILES := module1.c
- include $(BUILD_SHARED_LIBRARY)
- #
- #模块 2
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module2
- LOCAL_SRC_FILES := module2.c
- include $(BUILD_SHARED_LIBRARY)
在处理完这个Android.mk构建文档之后,Android NDK构建系统会产生libmodule1.so和libmodule2.so两个共享库。
3. 构建静态库
Android NDK构建系统也支持静态库。实际的Android应用程序并不直接使用静态库,而且应用程序包中也不包括静态库。
静态库能够用来构建共享库。比如。在将第三方代码加入到现有原生项目中时,不用直接将第三方源码包括在原生项目中,而是将第三方代码编译成静态库然后并入共享库,如程序:
- LOCAL_PATH := $(call my-dir)
- #
- # 第三方AVI库
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := avilib
- LOCAL_SRC_FILES := avilib.c platform_posix.c
- include $(BUILD_STATIC_LIBRARY)
- #
- # 原生模块
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module
- LOCAL_SRC_FILES := module.c
- LOCAL_STATIC_LIBRARIES := avilib
- include $(BUILD_SHARED_LIBRARY)
在将第三方代码模块生成静态库之后,共享库就能够通过将它的模块名加入到LOCAL_STATIC_LIBRARIES变量中来使用该模块。
4. 用共享库共享通用模块
静态库能够保证源码模块化。可是,当静态库与共享库相连时,它就变成了共享库的一部分。在多个共享库的情况下,多个共享库与同一个静态库连接时,须要将通用模块的多个副本与不同共享库反复相连,这样就添加了应用程序的大小。在这样的情况下,不用构建静态库。而是将通用模块作为共享库建立起来,而动态连接依赖模块以便消除反复的副本。如程序:
- LOCAL_PATH := $(call my-dir)
- #
- # 第三方AVI库
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := avilib
- LOCAL_SRC_FILES := avilib.c platform_posix.c
- include $(BUILD_SHARED_LIBRARY)
- #
- # 原生模块 1
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module1
- LOCAL_SRC_FILES := module1.c
- LOCAL_SHARED_LIBRARIES := avilib
- include $(BUILD_SHARED_LIBRARY)
- #
- # 原生模块 2
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module2
- LOCAL_SRC_FILES := module2.c
- LOCAL_SHARED_LIBRARIES := avilib
- include $(BUILD_SHARED_LIBRARY)
5. 在多个NDK项目间共享模块
同一时候使用静态库和共享库时,能够在模块间共享通用模块。
但要说明的是。全部这些模块必须属于同一个NDK项目。从R5版本号開始。Android NDK也同意在NDK项目间共享和重用模块。
考虑前面讲过的演示样例,能够通过下面步骤在多个NDK项目间共享avilib模块:
首先,将avilib源码移动到NDK项目以外的位置。比如:C:\android\shared-modules\ avilib。
为了避免命名冲突,文件夹结构也能够包括模块提供者的名字,比如:C:\ android\shared-modules \transcode\avilib。
注意:
在Android NDK构建系统中,共享模块路径不能包括空格。
作为共享模块,avilib须要自己的Android.mk文件,如程序:
- LOCAL_PATH := $(call my-dir)
- #
- #第三方AVI库
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := avilib
- LOCAL_SRC_FILES := avilib.c platform_posix.c
- include $(BUILD_SHARED_LIBRARY)
如今,能够将avilib模块从NDK项目的Android.mk文件里移除。为了使用这个共享模块,将以transcode/avilib为參数调用函数宏import-module部分加入在构建文档的末尾。为了避免构建系统的冲突。应该将import-module函数宏调用放在Android.mk文档的末尾。如程序:
- #
- # 原生模块
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module
- LOCAL_SRC_FILES := module.c
- LOCAL_SHARED_LIBRARIES := avilib
- include $(BUILD_SHARED_LIBRARY)
- $(call import-module,transcode/avilib)
import-module函数宏须要先定位共享模块,然后再将它导入到NDK项目中。默认情况下,import-module函数宏仅仅搜索<Android NDK>/sources文件夹。
为了搜索c:\android\shared-modules文件夹,定义一个名为NDK_MODULE_PATH的新环境变量并将它设置成共享模块的根文件夹。比如:c:\android\shared-modules。
6. 用Prebuilt库
使用共享模块要求有共享模块的源码,Android NDK构建系统简单地把这些源文件包括在NDK项目中并每次构建它们。自R5版本号以后。Android NDK也提供对Prebuilt库的支持。在以下的情况下,Prebuilt库是很实用的:
想在不公布源码的情况下将你的模块公布给他人。
想使用共享模块的预建版来加速构建过程。
虽然已经被编译了,但预建模块仍须要一个Android.mk构建文档。如程序:
- LOCAL_PATH := $(call my-dir)
- #
- # 第三方预构建AVI库
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := avilib
- LOCAL_SRC_FILES := libavilib.so
- include $(PREBUILT_SHARED_LIBRARY)
LOCAL_SRC_FILES变量指向的不是源文件。而是实际Prebuilt库相对于LOCAL_PATH的位置。
注意:
Prebuilt库定义中不包括不论什么关于该库所构建的实际机器体系结构的信息。
开发者须要确保Prebuilt库是为与NDK项目同样的机器体系结构而构建的。
PREBUILT_SHARED_LIBRARY变量指向prebuilt-shared-library.mk Makefile片段。它什么都没有构建。可是它将Prebuilt库拷贝到了NDK项目的libs文件夹下。通过使用PREBUILT_STATIC_LIBRARY变量,静态库能够像共享库一样被用作Prebuilt库,NDK项目能够像普通共享库一样使用Prebuilt库了。
- ...
- LOCAL_SHARED_LIBRARIES :=avilib
- …
7. 构建独立的可运行文件
在Android平台上使用原生组件的推荐和支持的方法是将它们打包成共享库。可是,为了方便測试和进行高速原型设计。Android NDK也支持构建独立的可运行文件。这些独立的可运行文件是不用打包成APK文件就能够拷贝到Android设备上的常规Linux应用程序,并且它们能够直接运行,而不通过Java应用程序载入。
生成独立可运行文件须要在Android.mk构建文档中导入BUILD_EXECUTABLE变量,而不是导入BUILD_SHARED_ LIBRARY变量,如程序:
- #
- # 独立的可运行的原生模块
- #
- include $(CLEAR_VARS)
- LOCAL_MODULE := module
- LOCAL_SRC_FILES := module.c
- LOCAL_STATIC_LIBRARIES := avilib
- include $(BUILD_EXECUTABLE)
BUILD_EXECUTABLE变量指向build-executable.mk Makefile片段,该片段包括了在Android平台上生成独立可运行文件的必要步骤。
独立可运行文件以与模块同样的名称被放在libs/<machine architecture>文件夹下。虽然放在该文件夹下。但在打包阶段它并没有被包括在APK文件里。
8. 其它构建系统变量
除了在前几节提到的变量之外,Android NDK构建系统还支持其它变量,本节将对这些变量进行简要说明。
构建系统定义的变量有:
TARGET_ARCH:目标CPU体系结构的名称,比如arm
TARGET_PLATFORM:目标Android平台的名称,比如:android-3
TARGET_ARCH_ABI:目标CPU体系结构和ABI的名称,比如:armeabi-v7a
TARGET_ABI:目标平台和ABI的串联,比如:android-3-armeabi-v7a
可被定义为模块说明部分的变量有:
LOCAL_MODULE_FILENAME:可选变量,用来又一次定义生成的输出文件名。默认情况下。构建系统使用LOCAL_MODULE的值作为生成的输出文件名,但变量LOCAL_MODULE_ FILENAME能够覆盖LOCAL_MODULE的值。
LOCAL_CPP_EXTENSION:C++源文件的默认扩展名是.cpp。这个变量能够用来为C++源码指定一个或多个文件扩展名。
- …
- LOCAL_CPP_ EXTENSION :=.cpp .cxx
- …
LOCAL_CPP_FEATURES:可选变量,用来指明模块所依赖的详细C++特性,如RTTI、exceptions等。
- …
- LOCAL_CPP_FEATURES :=rtti
- …
LOCAL_C_INCLUDES:可选文件夹列表,NDK安装文件夹的相对路径,用来搜索头文件。
- …
- LOCAL_C_INCLUDES :=sources/shared-module
- LOCAL_C_INCLUDES :=$(LOCAL_PATH)/include
- …
LOCAL_CFLAGS:一组可选的编译器标志,在编译C和C++源文件的时候会被传送给编译器。
- …
- LOCAL_CFLAGS :=-DNDEBUG -DPORT=1234
- …
LOCAL_CPP_FLAGS:一组可选的编译标志,在仅仅编译C++源文件时被传送给编译器。
LOCAL_WHOLE_STATIC_LIBRARIES:LOCAL_STATIC_LIBRARIES的变体,用来指明应该被包括在生成的共享库中的全部静态库内容。
(当几个静态库之间有循环依赖时,LOCAL_WHOLE_STATIC_LIBRARIES非常实用。)
LOCAL_LDLIBS:链接标志的可选列表,当对目标文件进行链接以生成输出文件时该标志将被传送给链接器。它主要用于传送要进行动态链接的系统库列表。比如:要与Android NDK日志库链接。使用下面代码:
- LOCAL_LDFLAGS :=? llog
LOCAL_ALLOW_UNDEFINED_SYMBOLS:可选參数。它禁止在生成的文件里进行缺失符号检查。若未定义。链接器会在符号缺失时生成错误信息。
LOCAL_ARM_MODE:可选參数,ARM机器体系结构特有变量,用于指定要生成的ARM二进制类型。默认情况下,构建系统在拇指模式下用16位指令生成,但该变量能够被设置为arm来指定使用32位指令。
- LOCAL_ARM_MODE :=arm
该变量改变了整个模块的构建系统行为;能够用.arm扩展名指定仅仅在arm模式下构建特定文件。
- LOCAL_SRC_FILES :=file1.c file2.c.arm
LOCAL_ARM_NEON:可选參数,ARM机器体系结构特有变量。用来指定在源文件里应该使用的ARM高级单指令流多数据流(Single Instruction Multiple Data,SIMD)(a.k.a. NEON)内联函数。
- LOCAL_ARM_NEON :=true
该变量改变了整个模块的构建系统行为;能够用.neon扩展名指定仅仅构建带有NEON内联函数的特定文件。
- LOCAL_SRC_FILES :=file1.c file2.c.neon
LOCAL_DISABLE_NO_EXECUTE:可选变量。用来禁用NX Bit安全特性。NX Bit代表Never Execute(永不运行),它是在CPU中使用的一项技术,用来隔离代码区和存储区。这样能够防止恶意软件通过将它的代码插入应用程序的存储区来控制应用程序。
- LOCAL_DISABLE_NO_EXECUTE :=true
LOCAL_EXPORT_CFLAGS:该变量记录一组编译器标志,这些编译器标志会被加入到通过变量LOCAL_STATIC_LIBRARIES或LOCAL_SHARED_LIBRARIES使用本模块的其它模块的LOCAL_CFLAGS定义中。
- LOCAL_MODULE := avilib
- ...
- LOCAL_EXPORT_CFLAGS := − DENABLE_AUDIO
- ...
- LOCAL_MODULE := module1
- LOCAL_CFLAGS := − DDEBUG
- ...
- LOCAL_SHARED_LIBRARIES := avilib
编译器在构建module1时会以-DENABLE_AUDIO –DDEBUG标志运行。
LOCAL_EXPORT_CPPFLAGS:和LOCAL_EXPORT_CLAGS一样,可是它是C++特定代码编译器标志。
LOCAL_EXPORT_LDFLAGS:和LOCAL_EXPORT_CFLAGS一样。但用作链接器标志。
LOCAL_EXPORT_C_INCLUDES:该变量同意记录路径集,这些路径会被加入到通过变量LOCAL_STATIC_LIBRARIES或LOCAL_SHARED_LIBRARIES使用该模块的LOCAL_C_INCLUDES定义中。
LOCAL_SHORT_COMMANDS:对于有大量资源或独立的静态/共享库的模块,该变量应该被设置为true。诸如Windows之类的操作系统仅仅同意命令行最多输入8 191个字符;该变量通过分解构建命令使其长度小于8 191个字符。在较小的模块中不推荐使用该方法,由于使用它会让构建过程变慢。
LOCAL_FILTER_ASM:该变量定义了用于过滤来自LOCAL_SRC_FILES变量的装配文件的应用程序。
9. 其它的构建系统函数宏
本节概括了Android NDK构建系统支持的其它函数宏。
all-subdir-makefiles:返回当前文件夹的全部子文件夹下的Android.mk构建文件列表。比如。调用下面命令能够将子文件夹下的全部Android.mk文件包括在构建过程中:
- include $(call all-subdir-makefiles)
this-makefile:返回当前Android.mk构建文件的路径。
parent-makefile:返回包括当前构建文件的父Android.mk构建文件的路径。
grand-parent-makefile:和parent-makefile一样但用于祖父文件夹。
10. 定义新变量
开发者能够定义其它变量来简化他们的构建文件。
以LOCAL_和NDK_前缀开头的名称预留给Android NDK构建系统使用。
建议开发者定义的变量以MY_开头,如程序:
- ...
- MY_SRC_FILES := avilib.c platform_posix.c
- LOCAL_SRC_FILES := $(addprefix avilib/, $(MY_SRC_FILES))
- ...
11. 条件操作
Android.mk构建文件也能够包括关于这些变量的条件操作,比如:在每一个体系结构中包括一个不同的源文件集,如程序:
- ...
- ifeq ($(TARGET_ARCH),arm)
- LOCAL_SRC_FILES + = armonly.c
- else
- LOCAL_SRC_FILES + = generic.c
- endif
- ...
Application.mk
Application.mk是Android NDK构建系统使用的一个可选构建文件。和Android.mk文件一样,它也被放在jni文件夹下。Application.mk也是一个GUN Makefile片段。它的目的是描写叙述应用程序须要哪些模块。它也定义全部模块的通用变量。
下面是Application.mk构建文件支持的变量:
APP_MODULES:默认情况下,Android NDK构建系统构建Android.mk文件声明的全部模块。
该变量能够覆盖上述行为并提供一个用空格分开的、须要被构建的模块列表。
APP_OPTIM:该变量能够被设置为release或debug以改变生成的二进制文件的优化级别。
默认情况下使用的是release模式。而且此时生成的二进制文件被高度优化。该变量能够被设置为debug模式以生成更easy调试的未优化二进制文件。
APP_CLAGS:该变量列出了一些编译器标志,在编译不论什么模块的C和C++源文件时这些标志都会被传给编译器。
APP_CPPFLAGS:该变量列出了一些编译器标志。在编译不论什么模块的C++源文件时这些标志都会被传给编译器。
APP_BUILD_SCRIPT:默认情况下。Android NDK构建系统在项目的jni子文件夹下查找Android.mk构建文件。
能够用该变量改变上述行为,并使用不同的生成文件。
APP_ABI:默认情况下,Android NDK构建系统为armeabi ABI生成二进制文件。
能够用该变量改变上述行为,并为其它ABI生成二进制文件,比如:
- APP_ABI := mips
另外,能够设置多个ABI
- APP_ABI := armeabi mips
为全部支持的ABI生成二进制文件
- APP_ABI := all
APP_STL:默认情况下,Android NDK构建系统使用最小STL执行库,也被称为system库。能够用该变量选择不同的STL实现。
- APP_STL :=stlport_shared
APP_GNUSTL_FORCE_CPP_FEATURES:与LOCAL_CPP_EXTENSIONS变量相似。该变量表明全部模块都依赖于详细的C++特性,如RTTI、exceptions等。
APP_SHORT_COMMANDS:与LOCAL_SHORT_COMMANDS变量相似,该变量使得构建系统在有大量源文件的情况下能够在项目中使用更短的命令。
Android NDK编程浅入深出之--Android.mk的更多相关文章
- 浅入深出之Java集合框架(上)
Java中的集合框架(上) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架 ...
- 浅入深出之Java集合框架(中)
Java中的集合框架(中) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,如果已经有java基础的小伙伴可以直接跳到<浅入深出之Java集合框架 ...
- 浅入深出之Java集合框架(下)
Java中的集合框架(下) 由于Java中的集合框架的内容比较多,在这里分为三个部分介绍Java的集合框架,内容是从浅到深,哈哈这篇其实也还是基础,惊不惊喜意不意外 ̄▽ ̄ 写文真的好累,懒得写了.. ...
- 『浅入深出』MySQL 中事务的实现
在关系型数据库中,事务的重要性不言而喻,只要对数据库稍有了解的人都知道事务具有 ACID 四个基本属性,而我们不知道的可能就是数据库是如何实现这四个属性的:在这篇文章中,我们将对事务的实现进行分析,尝 ...
- 浅入深出Vue:环境搭建
浅入深出Vue:环境搭建 工欲善其事必先利其器,该搭建我们的环境了. 安装NPM 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版本的NodeJS Windows安装程序 下载下来后,直 ...
- 浅入深出Vue:工具准备之PostMan安装配置及Mock服务配置
浅入深出Vue之工具准备(二):PostMan安装配置 由于家中有事,文章没顾得上.在此说声抱歉,这是工具准备的最后一章. 接下来就是开始环境搭建了~尽情期待 工欲善其事必先利其器,让我们先做好准备工 ...
- 浅入深出Vue:工具准备之WebStorm安装配置
浅入深出Vue之工具准备(一):WebStorm安装配置 工欲善其事必先利其器,让我们先做好准备工作吧 导航篇 WebStorm安装配置 所有工具的下载地址都可以在导航篇中找到,这里我们下载的是最新版 ...
- 浅入深出Vue系列
浅入深出Vue导航 导航帖,直接点击标题即可. 文中所有涉及到的资源链接均在最下方列举出来了. 前言 基础篇 浅入深出Vue:工具准备之WebStorm搭建及配置 浅入深出Vue之工具准备(二):Po ...
- 浅入深出Vue:前言
浅入深出Vue系列文章 之前大部分是在做后端,后来出于某些原因开始接触Vue.深感前端变化之大,各种工具.框架令人眼花缭乱.不过正是这些变化,让前端开发更灵活. 博主在刚开始时,参考官网的各个步骤以及 ...
随机推荐
- 为公司架构一套高质量的 Vue UI 组件库
有没有曾遇过,产品要我们实现一个功能,但是 iview 或者 elementui 不支持,我们然后义正言辞的说,不好意思,组件库不支持,没法做到. 有没有曾和设计师争论得面红耳赤,其实也是因为组件库暂 ...
- 关于flock文件锁的阻塞与非阻塞
阻塞模式,程序会一直等待. <?php $fp = fopen("lock.txt", "r"); if(flock($fp,LOCK_EX)) { // ...
- tornado框架基础11-tornado异步
01 同步和异步 生活中常常会遇到在超市排队买东西的情况,排在你前面的人没有结算完成,你就无法付账,在计算机中也有类似的情形,一个程序在执行之前,需要等待其他的程序执行完成,大家还能举出其他的例子吗? ...
- LeetCode(86) Partition List
题目 Given a linked list and a value x, partition it such that all nodes less than x come before nodes ...
- Uva 12325 Zombie's Treasure Chest (贪心,分类讨论)
题意: 你有一个体积为N的箱子和两种数量无限的宝物.宝物1的体积为S1,价值为V1:宝物2的体积为S2,价值为V2.输入均为32位带符号的整数.你的任务是最多能装多少价值的宝物? 分析: 分类枚举, ...
- 局域网虚拟机端口映射访问apache
如果我们在虚拟机内搭建好服务器后,希望可以在局域网内的设备上都能访问到这个虚拟服务器,就可以参照以下步骤来操作.其中包括了很多遇到的坑.先说说我的环境是 宿主机:windows 8.1 虚拟机:vmw ...
- python010 Python3 元组
Python3 元组Python 的元组与列表类似,不同之处在于元组的元素不能修改.元组使用小括号,列表使用方括号.元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可.如下实例: tup1 = ...
- Leetcode 229.求众数II
求众数II 给定一个大小为 n 的数组,找出其中所有出现超过 ⌊ n/3 ⌋ 次的元素. 说明: 要求算法的时间复杂度为 O(n),空间复杂度为 O(1). 示例 1: 输入: [3,2,3] 输出: ...
- Linux下出现launch failed.Binary not found的解决方案
Linux下出现launch failed.Binary not found的解决方案: Project->Properties->C/C++Build->Settings-> ...
- php 翻转字符串
//方法一 function strrev_charset($string,$charset='utf-8'){ if(!is_string($string) || !mb_check_encodin ...