@senspond
>
Android Native C++ 로그를 안드로이드 logcat로 확인하기
Java 기반 이미치 처리 앱을 개발하고 있는데, OpenCV Java sdk로 개발을 했다.
일부 복잡한 연산은 Native C++ 코드로 처리하는 것이 성능면에서 더 낳을 것 같다는 생각을 하고,
이제는 너무 오래되서 기억도 안나는 C++ 코드를 다시 꺼내들기 시작했다.
몇일동안 Rust로 Pytorch 학습시키고 ONNX 모델 추론을 해봤는데,
Rust를 하면 할 수록, C++를 깊이있게 안다면 C++로 하는게 더 낳을 것 같다는 생각마저 들었다.
일단 Rust는 레퍼런스가 너무 없어서… 힘들다.
아무튼 Android에도 Rust를 도입하고 싶었는데, C++보다 빌드파일 용량이 증가하는것 같고
설정도 너무 까다로워서 그냥 C++로…
그런데 문제는 C++에서 오류가 발생했을 때, 로깅을 남겨서 logcat에서 확인 할 수 있는 방법이 필요했다.
만약 이런것도 Rust로 해야한다면, 어디서 찾아봐도 안나오고 (일단 현재로썬 커뮤니티가 너무 부족)
#include <jni.h>
#include <string>
#include <opencv2/opencv.hpp>
#include <android/log.h> // 안드로이드 로그
// #define 매크로 (전처리기)
#define LOG_TAG "OpenCV"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
android/log.h 포함해주고
오류가 나더라도 App이 꺼지지 않고 LOG를 남기도록
extern "C"
JNIEXPORT void JNICALL
Java_com_rgbitsoft_myapplication_MainActivity_convertRGBtoGray(JNIEnv *env,
jobject thiz,
jlong mat_addr_input,
jlong mat_addr_result) {
// 네이티브 코드에서 안전하게 예외처리
try {
// 포인터 변환 전 NULL 체크
if (mat_addr_input == 0 || mat_addr_result == 0) {
LOGE("Error: Null Mat address received.");
return;
}
// 안전한 포인터 캐스팅
Mat *matInput = reinterpret_cast<Mat *>(mat_addr_input);
Mat *matResult = reinterpret_cast<Mat *>(mat_addr_result);
// 입력 Mat의 유효성 검사
if (matInput->empty()) {
LOGE("Error: Input Mat is empty!");
return;
}
// 출력 Mat이 초기화되지 않았다면, 입력과 동일한 크기 및 타입으로 초기화
if (matResult->empty()) {
*matResult = Mat(matInput->size(), CV_8UC1);
}
// 컬러 -> 그레이스케일 변환
cvtColor(*matInput, *matResult, COLOR_RGBA2GRAY);
} catch (const cv::Exception &e) {
LOGE("OpenCV Exception: %s", e.what());
} catch (const std::exception &e) {
LOGE("Standard Exception: %s", e.what());
} catch (...) {
LOGE("Unknown Exception occurred.");
}
}
복잡한 연산은 아니지만, 예제 코드로 만들었다.
public class MainActivity extends AppCompatActivity {
// Used to load the 'myapplication' library on application startup.
static {
System.loadLibrary("opencv_java4");
System.loadLibrary("myapplication");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
// 예제 Mat 객체 초기화 및 처리
Mat inputMat = new Mat(); // 입력 Mat 객체
Mat resultMat = new Mat(); // 결과 Mat 객체
// inputMat = Mat.ones(100, 100, CvType.CV_8UC3); // 일부로 예외 발생시키도록 주석
// 네이티브 메서드 호출
convertRGBtoGray(inputMat.getNativeObjAddr(), resultMat.getNativeObjAddr());
inputMat.release();
System.out.println(resultMat.dump());
}
public native void convertRGBtoGray(long matAddrInput, long matAddrResult);
}
이제 logcat에 Native C++에서 처리한 로깅이 남는다.
안녕하세요. Red, Green, Blue 가 만나 새로운 세상을 만들어 나가겠다는 이상을 가진 개발자의 개인공간입니다.
현재글에서 작성자가 발행한 같은 카테고리내 이전, 다음 글들을 보여줍니다
@senspond
>