// 초기화
List<int> numbers = [100, 200, 300];
List<int> numbers2 = [0, ...numbers];
// 병합
List<int> numbers3 = numbers + numbers2;
// 요소접근
int first = numbers[0];
// 순회
for ( int each in numbers ){}
Set - 중복값 허용하지 않음
// 초기화
Set<int> numbers = {100, 200, 300};
Set<int> numbers2 = {0, 100, ...numbers};
// 요소접근 - error
// int first = numbers[0];
// 순회
for ( int each in numbers ){}
// 집합
numbers.union(numbers2);
numbers.intersection(numbers2);
numbers.difference(numbers2);
# Error checking if [ ! -d "${ANDROID_NDK_ROOT}" ]; then echo "ERROR: ANDROID_NDK_ROOT is not a valid path for ${USER}. Please set it." echo "ANDROID_NDK_ROOT is '${ANDROID_NDK_ROOT}'" exit 1 fi
# Error checking if [ ! -d "${ANDROID_SDK_ROOT}" ]; then echo "ERROR: ANDROID_SDK_ROOT is not a valid path for ${USER}. Please set it." echo "ANDROID_SDK_ROOT is '${ANDROID_SDK_ROOT}'" exit 1 fi
* 기술해야 하는 경로는 Android Studio의 [File>Project Structure...] 메뉴를 선택 후, SDK Location에서 확인 할 수 있다.
4) (아마도 windows에서 발생하는) ndk-build 관련 에러
위의 설정을 마친 후 빌드 커맨드를 실행하면 ndk-build관련 에러가 발생한다.
ERROR: ndk-build is not on-path for . Please set it
cryptest-android-mk.sh 을 편집기로 오픈한 후, ndk-build 라고 기술된 부분을 ndk-build.cmd 로 변경해 준다.
( 총 3군데가 존재한다)
# Error checking if [ -z "$(command -v ndk-build.cmd 2>/dev/null)" ]; then echo "ERROR: ndk-build is not on-path for ${USER}. Please set it." echo "PATH is '${PATH}'" exit 1 fi
# Clean all past artifacts ndk-build.cmd APP_ABI=all NDK_PROJECT_PATH="${NDK_PROJECT_PATH}" NDK_APPLICATION_MK="${NDK_APPLICATION_MK}" distclean &>/dev/null
if ndk-build.cmd -j "${MAKE_JOBS}" APP_ABI="${platform}" NDK_PROJECT_PATH="${NDK_PROJECT_PATH}" NDK_APPLICATION_MK="${NDK_APPLICATION_MK}" V=1;
(제공되는 빌드 스크립트는 linux를 기준으로 작성되어있고, linux는 ndk-build, windows는 ndk-build.cmd 가 아닌가 추정해 본다)
5) 빌드
이제 빌드 스크립트를 실행하여 crypto++라이브러리를 빌드한다.
$bash cryptest-android-mk.sh
정상적이라면 빌드에 사용될 Android.mk와 Application.mk를 다운받은 후, 빌드가 진행된다.
추가로 다운로드 되는 hxx,cxx은 라이브러리 테스트를 위한 소스로 크게 신경쓰지 않아도 된다.
기본적으로 4개의 플랫폼용 라이브러리를 생성하며 문제없이 생성이 완료되면 아래와 같이 표시된다.
빌드시 시간이 꽤 소요되는데, 필요한 플랫폼만 빌드하려면 sh파일의 아래 부분에 필요한 플랫폼만 기술하면 된다.
PLATFORMS=(armeabi-v7a arm64-v8a x86 x86_64)
6)라이브러리 확인
빌드를 실행한 폴더의 [libs] 폴더에 각 플랫폼별 바이너리(*.so)가 생성된다.
각각의 폴더 내에는 아래와 같은 4개의 파일이 생성되는데
실제 crypto++ 라이브러리 구동에 필요한 파일은
libcryptopp_shared.so 와
libc++_shared.so 파일이다
(나머지는 라이브러리 테스트를 위한 파일이므로 무시한다)
libcryptopp_shared.so 는 crypto++의 구현을 포함하고 있는 라이브러리 이며
libc++_shared.so 는 C++ 표준 라이브러리 이다.
libcryptopp_shared.so 이 정상적으로 로드되기 위해서는 libc++_shared.so이 필수적으로 필요한데
이에 대해서는 아래에서 다시 설명한다.
2) 빌드된 동적라이브러리(.so)파일을 링크하여 사용하도록 android.mk 구성
1) 폴더 구성
이제 libcryptopp_shared.so를 링크하기 위해 빌드된 libcryptopp_shared.so 파일을 android 프로젝트에 복사해야 한다.
기존의 Native code(c++) 파일들이 [Project Root]/app/src/main/jni]폴더 에 존재하고
crypto++ 관련 headr파일은 [jni/include/cryptopp]에
crypto++ 관련 라이브러리는 [jni/libs/cryptopp]에 위치하도록 구성하는 것을 가정한다.
2) 파일 복사
빌드에 사용된 crypto++ 소스중 헤더파일(h)을 [jni/include/cryptopp] 폴더에 복사하고
빌드된 crypto++ 라이브러리를 [jni/libs/cryptopp]에 복사한다.
( 지원하고자 하는 플랫폼(ABI)에 해당하는 폴더를 복사하면 되며, so 파일 중 libcryptopp_shared.so 만 복사한다.
libc++_shared.so 파일은 Android.mk구성을 통해 NDK의 표준 파일을 사용하도록 구성한다.)
아래와 같은 형태로 구성되면 되겠다.
jni
- libs
- cryptopp
- arm64-v8a / libcryptopp_shared.so
- armeabi-v7a / libcryptopp_shared.so
- x86 / libcryptopp_shared.so
- x86_64 / libcryptopp_shared.so
3) crypto++ 링크를 위한 Android.mk 구성
이제 기존의 모듈이 crypto++ 파일을 포함하도록 android.mk를 구성하면 된다.
foo.cpp 소스가 crypto++ 라이브러리를 사용한다 가정할때 아래와 같은 구성으로 cryptopp를 링크 할 수 있다.
WebAssembly는 최신 웹 브라우저에서 실행할 수 있는 새로운 유형의 코드이며 새로운 기능과 성능 면에서 큰 이점을 제공합니다. 직접 코드를 작성하는 것이 아니라 C, C ++, RUST 등의 저급 소스 언어를 효과적으로 컴파일하도록 고안되었습니다.
이는 웹 플랫폼에 큰 영향을 미칩니다. 이전에 불가능했던 웹에서 실행되는 클라이언트 응용 프로그램을 사용하여 웹에서 여러 언어로 작성된 코드를 네이티브에 가까운 속도로 실행하는 길을 제공합니다.
게다가 WebAssembly 코드를 사용하여 이를 활용하는 방법을 알 필요조차 없습니다. WebAssembly 모듈을 웹 (또는 Node.js) 앱으로 가져와 JavaScript를 통해 사용할 수 있도록 할 수 있습니다. JavaScript 프레임 워크는 WebAssembly를 사용하여 대규모 성능 이점과 새로운 기능을 제공하면서도 웹 개발자가 쉽게 기능을 사용할 수 있도록 할 수 있습니다.
var name: String = "tom"
var age: Int = 18
var nameVar = "tom"
var age = 18
함수
fun sum(num1:Int, num2:Int) : Int {
return num1+num2
}
fun sum1(num1:Int, num2:Int) : Int = num1 + num2
fun sum3(num1:Int, num2:Int) = num1 + num2
fun add10(num1:Int, num2:Int = 10) = num1 + num2
클래스
class Person{
public var name: String = ""
protected var age: String = ""
private var phone: String = ""
internal var address: String = ""
}
Constructor
Primary constructor(주 생성자)
class Person() {
public var name: String = ""
protected var age: String = ""
private var phone: String = ""
internal var address: String = ""
}
class Person() {
public var name: String = ""
}
class Person(_name: String) {
var name: String = _name
}
class Person(var name: String = "") {
}
Secondary constructor(부 생성자)
* 주 생성자 없음
class Person {
var name: String = ""
var age: Int = 18
constructor(_name: String){
this.name = _name
}
constructor(_name: String, _age: Int){
this.name = _name
this.age = _age
}
}
* 주 생성자 + 부 생성자 ( 부생성자는 반드시 주생성자를 재호출 해야 한다 --> 주생성자는 반드시 호출 되어야 한다.)
class Person(var _name: String) {
var name: String = ""
var age: Int = 18
constructor(_name: String, _age: Int) : this(_name){
this.age = _age
}
}
* 인자에 대한 디폴트 값을 전달받기 위해 부 생성자를 여러개 만들지 않아도, 디폴트 값을 활용하여 기능을 제공할 수 있다.
class Person(var _name: String, var age: Int = 18, var sex: String = "male" )
Initializer Block(초기화 블록)
* 초기화 블록은 주 생성자 호출 직후 실행되며, 부 생성자 보다 먼저 실행된다.
* 초기화 블록은 주 생성자가 없더라도, 부 생성자 보다 먼저 실행된다.
class Person{
var _name: String = ""
init {
println("initial block")
}
}
// Find the Mat classe
jclass matClass = env->FindClass("org/opencv/core/Mat");
// Get Mat class's methods<getNativeObjAddr()>
jmethodID getNativeObjAddrMethod = env->GetMethodID(matClass, "getNativeObjAddr", "()J");
native code에서 자바 클래스를 액세스 하기위해 java class나 Method를 구하는 경우,
Debug모드에서 잘 동작하던 코드가 Release 모드에서
JNI DETECTED ERROR IN APPLICATION: JNI NewStringUTF called with pending exception java.lang.NoSuchMethodError: no non=static mathod xxxxxxx
와 같은 에러를 뱉어 내며 Crash나는 현상이 발생할 수 있다.
이러한 에러는 android app 빌드시, 자바 클래스가 난독화 되어 class나 method를 찾지 못하여 발생하는 것으로 보인다.