This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

*/
레이블이 C인 게시물을 표시합니다. 모든 게시물 표시
레이블이 C인 게시물을 표시합니다. 모든 게시물 표시

Python - Bytes, bytearray vs c struct variable

Python에서 bytes, bytearray 를 다룰 때 참고

Format string - Byte order, size, alignment

기본적으로 C 유형은 시스템의 기본 형식 및 바이트 순서로 표시
첫 번째 문자가 이들 중 하나가 아니면 '@'으로 가정
네이티브 바이트 순서는 호스트 시스템에 따라 big-endian 또는 little-endian으로 구분. 예를 들어 Intel x86 및 AMD64 (x86-64)는 little-endian.  Motorola 68000과 PowerPC G5는 big-endian



Format character



Example

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
b'\x01\x00\x02\x00\x03\x00\x00\x00'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(256, 512, 50331648)

>>> pack('<hhl', 1, 2, 3)
b'\x01\x00\x02\x00\x03\x00\x00\x00'
>>> pack('>hhl', 1, 2, 3)
b'\x00\x01\x00\x02\x00\x00\x00\x03'

>>> unpack('<hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(256, 512, 50331648)
>>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)

Windows PC에서 endian을 지정하지 않고 했을 경우 => 네이티브로 판단하여 intel계열의 little-endian 으로 출력

>>> pack('hhl', 1, 2, 3) # Native'@'를 지정한 것으로 처리
b'\x01\x00\x02\x00\x03\x00\x00\x00'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(256, 512, 50331648)


Little-endian vs Big-endian

>>> pack('<hhl', 1, 2, 3)           # little-endian
b'\x01\x00\x02\x00\x03\x00\x00\x00'
>>> pack('>hhl', 1, 2, 3)           # big-endian
b'\x00\x01\x00\x02\x00\x00\x00\x03'

>>> unpack('<hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')     # little-endian
(256, 512, 50331648)
>>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')     # big-endian
(1, 2, 3)



Visual Studio Code에 ESP32 IDF 개발환경 세팅하기

ESP-IDF VS Code Extension

Visual Studio Code에 Espressif IoT Development Framework을 개발, 빌드, 롬라이팅, 모니터링, 디버그 등을 지원

목차


전제조건

Extention을 설치하기 전에 사용하고자 하는 환경에 따라 아래의 프로그램들을 설치해야 한다.

LinuxMacOSWindows
Python 3.5+Python 3.5+Python 3.5+
PIPPIPPIP
GitGitGit
CMakeCMakeC++ Build Tool
Ninja-buildNinja-buildRust

Windows에서 C++ Build Tools 설치

위의 링크에서 다운받은 설치파일을 실행 시키고 첫번째 항목("C++ build tools")을 선택하고 Install 버튼을 누른다.

설치가 완료되고 나서 설치가 잘되었는지 아래와 같이 확인한다.

윈도우 시작메뉴 에서 Development Command Prompt for VS를 실행시킨다.


Command prompt에서 cl.exe 명령어를 실행했을 때 아래와 같이 실행되는지 확인



ESP-IDF Extension설치 하기

VS Code에서 Extension 메뉴를 누르거나 <Ctrl> + <Shift> + <x> 키를 눌러 EXTENSIONS: MARKETPLACE 검색창에 "esp32" 를 입력하여 Espressif IDF를 찾아 install 한다.


install이 끝나면 메뉴에서 View -> Command Palette 에서 "configure esp-idf extension"를 입력하여 "ESP-IDF:Configure ESP-IDF extension"을 선택한다.

EXPRESS를 선택

ESP-IDF 컨테이너를 설치할 디렉토리를 변경하고자하면 변경하고 아니면 그래도 install버튼 클릭


설정이 끝나면 해당 윈도우를 닫는다.




Image buffer를 Bitmap file format으로 저장하기(RGB)

Image처리를 하다보면 memory buffer에 있는 image raw데이터를 BMP포멧으로 저장할 필요가 있다.
RGB Buffer(24bit)를 widows bitmap format으로 저장하는 함수

// _fname : 저장할 파일 명( xxx.bmp )
// _buf : RGB 순서로 구성된 Image buff
// _w, _h : image width, height
void saveBMPfile(char *_fnameuchar* _bufint _wint _h)
{
    int filesize = 54 + _w * _h * 3;
    unsigned char bmpfileheader[14] = {'B','M'0,0,0,00,00,054,0,0,0};
    unsigned char bmpinfoheader[40] = {40,0,0,00,0,0,00,0,0,01,08,0};
    unsigned char bmppad[3] = {0,0,0};

    bmpfileheader2] = (unsigned char)(filesize    );
    bmpfileheader3] = (unsigned char)(filesize>> 8);
    bmpfileheader4] = (unsigned char)(filesize>>16);
    bmpfileheader5] = (unsigned char)(filesize>>24);

    bmpinfoheader4] = (unsigned char)( _w    );
    bmpinfoheader5] = (unsigned char)( _w>> 8);
    bmpinfoheader6] = (unsigned char)( _w>>16);
    bmpinfoheader7] = (unsigned char)( _w>>24);
    bmpinfoheader8] = (unsigned char)( _h    );
    bmpinfoheader9] = (unsigned char)( _h>> 8);
    bmpinfoheader[10] = (unsigned char)( _h>>16);
    bmpinfoheader[11] = (unsigned char)( _h>>24);

    FILE* fp;
    fp =fopen(_fname, "wb");
    if(fp!=NULL) {
        fwrite(bmpfileheader, 114, fp);
        fwrite(bmpinfoheader, 140, fp);
        fwrite(_buf, _w*_h, 3, fp);
        fclose(fp);
    }
}


* Gray Bufferer 저장하기 : 링크

관련문서

Image buffer를 Bitmap file format으로 저장하기(Gray image)

 Image처리를 하다보면 memory buffer에 있는 image raw데이터를 BMP포멧으로 저장할 필요가 있다.

Gray Buffer(8bit)를 widows bitmap fotmat으로 저장하는 함수

// _fname : 저장할 파일 명( xxx.bmp )
// _buf : RGB 순서로 구성된 Image buff
// _w, _h : image width, height
void saveBMPfile(char *_fnameuchar* _bufint _wint _h)
{
    int filesize = 54 + 256*4 + _w*_h;
    unsigned char bmppalete[256*4];
    unsigned char bmpfileheader[14] = {'B','M'0,0,0,00,00,054+256*4,0,0,0};
    unsigned char bmpinfoheader[40] = {40,0,0,00,0,0,00,0,0,01,08,0};
    unsigned char bmppad[3] = {0,0,0};

// BMP File header의 내용을 채워넣는다
// File의 크기
    bmpfileheader2] = (unsigned char)(filesize    );
    bmpfileheader3] = (unsigned char)(filesize>> 8);
    bmpfileheader4] = (unsigned char)(filesize>>16);
    bmpfileheader5] = (unsigned char)(filesize>>24);

// Image buffer의 Width
    bmpinfoheader4] = (unsigned char)( _w    );
    bmpinfoheader5] = (unsigned char)( _w>> 8);
    bmpinfoheader6] = (unsigned char)( _w>>16);
    bmpinfoheader7] = (unsigned char)( _w>>24);
// Image buffer의 Height
    bmpinfoheader8] = (unsigned char)( _h    );
    bmpinfoheader9] = (unsigned char)( _h>> 8);
    bmpinfoheader[10] = (unsigned char)( _h>>16);
    bmpinfoheader[11] = (unsigned char)( _h>>24);

// Pallet 정보 Windows Format의 구성 : RGBx 4Byte
// 8bit Image의 경우 Pallet의 크기 2^8 = 256
// Gray Image의 경우 RGB 동일값
    for(int i=0; i<256;i++) {
        bmppalete[i*4] = bmppalete[i*4+1] = bmppalete[i*4+2] = i;
        bmppalete[i*4+3] = 0;
    }
    FILE* fp;
    fp = fopen(_fname, "wb");
    if(fp!=NULL) {
        fwrite(bmpfileheader, 114, fp);
        fwrite(bmpinfoheader, 140, fp);
        fwrite(bmppalete, 1256*4, fp);
        fwrite(_buf, _w*_h, 1, fp);
        fclose(fp);
    }
}

* Color Buffer(RGB) 저장 : https://amosground.blogspot.com/2020/10/image-buffer-bitmap-file-format-rgb.html

관련문서

PC에서 ARM용 크로스 컴파일 후 strip 시 오류 발생

 OpenCV를 ARM용으로 Cross Compile후 strip실행시 아래와 같은 오류 발생

strip -s *.so   
    strip: Unable to recognise the format of the input file 'libopencv_calib3d.so'

원인은 strip을 호스트용을 사용해서 발생한 것으로 ARM용으로 strip을 할수 있는 arm-linux-gnueabi-strip을 사용하면 정상적으로 strip이 되는것을 확인할 수 있다.

arm-linux-gnueabi-strip -s *.so



VisualStudio Code 에서 C++ 사용하기

Windows 10 OS에서 Visual Studio Code 환경에서 C++ 컴파일 환경을 구축해보자

Visual Studio Code 다운로드

우선 Visual Studio Code를 여기(code.visualstudio.com)서 다운로드 받아 설치합니다.

C++개발을 위한 VSC(Visual Studio Code) 설정

VSC를 다운받아 설치하고 실행하면 환영창이 나오고, 좌측에 파일탐색, 찾기,  Git, 실행/디버그, 확장(extension) 탭 5개가 있는것을 확인할 수 있다.

제일 아래쪽에 위치한 녹색으로 표시한 확장 탭을 누르고, 노란색으로 표기한 검색창에 "C++"을 입력하면 위의 사진과 같이 검색 결과 표시된다.
C++로 개발하기위해서는 2개의 extension을 설치해야 되는데 첫번째 확장은 결과리스트의 맨위에 있는 "C/C++"이다. 해당 항목(빨간색영역에 있는)의 Install을 눌러 설치한다. 이 확장은 VSC에서 C/C++언어을 지원하기 위한 추가하는 것이며, Compiler는 포함되어 있지 않다.
두번째 확장은 "easy c++"을 검색하여 설치한다.

Compiler 설치

C++ 컴파일러를 설치하는 방법은 아래와 같이 여러가지 방법이 있는데 여기서는 Windows Subsystem for Linux(WSL)을 설치한다.
  • Microsoft C++ compiler(MSVC) on Windows
  • GCC and Minggw-w64 on Windows
  • GCC and Windows Subsystem for Linux(WSL)
  • ...
WSL설치 후 Ubuntu 터미널에서 아래와 같이 build package들을 설치한다.
$ sudo apt install build-essential gdb

Code 작성하기

프로젝트생성을위해 폴더 열기(Ctrl+K Ctrl+O)하여 폴더를 선택한다.
F1키를 눌러 "easy"를 검색하여 Easy Cpp/C++: Create new C++ project를 선택
[WSL] Windows Subsystem for Linux를 선택 
비어 있던 프로젝트에 .vscode, bin, include, lib, src폴더와 main.cpp, Makefile등이 생성되며 좌하단에 Build 버튼과 Build&Run버튼이 생성된다.
아래쪽에 Build & Run버튼을 클릭하면 하단의 터미널창에 빌드 결과와 Hello Easy C++ project라고 실행 결과가 출력되는 것을 볼 수 있다.

Reference




 


Protocol buffers ?

 프로토콜 버퍼란?

구글에서 만들어서 공개한 구조화된 데이터를 직렬화 하기 위한 언어중립적이고, 플랫폼 중립적인 확장 메카니즘이며, 저장을 목적으로 서로 통신할 프로그램을 개발할 때 유용하다.

지원 언어 : C++, Python, JAVA, GO


위키피디아 : 프로토콜버퍼

구글 개발자 싸이트

64bit Linux환경에서 64/32bit으로 compile

64bit Linux환경에서는 기본적으로 gcc를 사용할 경우 64bit용으로 컴파일된다. 당연히 32bit Linux환경에서는 32bit용으로 컴파일된다.

gcc에서 -m옵션으로 비트수를 설정할수 있다
-m32 : 32bit binary
-m64 : 64bit binary

현재사용하고 있는 환경과 다른 bit용으로 컴파일하고자 할때 gcc-multilib의 설치가 필요하다.
sudo apt-get install gcc-multilib

해당라이브러리가 설치되기 전에 -m옵션을 통해 컴파일하면 아래와 같은 오류가 발생한다.
unrecognized emulation mode: 32
라이브러리 설치하면 정상적으로컴파일되는것을 확인 할 수 있다.

32bit로 컴파일
gcc -o test test.cpp -m32

64bit로 컴파일
gcc -o test test.cpp -m64

vector에 할당한 메모리 해제 방법


new로 할당한 객체를 제대로 해제하지 않으면 메모리 릭이 발생.
다음과 같이 해제하여 메모리 릭 방지.



std::vector<strFileInfo*>  FileList;

// new 메모리할당 및 추가
strFileInfo* ifo = new strFileInfo();
:
FileList.push_back(ifo );

// 해제시 erase() 수행후 delete
strFileInfo *ifo = *iter;
iter = FileList.eraseiter );
delete ifo;


WinInet을 이용하여 http 서버에서 파일 다운로드 받기

Header
   wininet.h
API
   InternetOpen( )                     - WinInet 함수들을 초기화
   InternetConnect( )                 - Http혹은 FTP 사이트 연결
   HttpOpenRequest( )               - HTTP Request handle 생성
   HttpSendRequest( )                - HTTP 서버로 Request 전달
   HttpQueryInfo( )                    - 파일을 전체크기
   InternetQueryDataAvailable( )   - 서버가 바로보낼수 있는 크기를 알려줌
   InternetReadFile( )                  - 서버로부터 지정된 크기만큼 파일을 읽어옴
   InternetCloseHandle( )             - 열려있는 핸들을 닫음


예제
#include < wininet.h >
  HINTERNET hOpen, hConnect, hReq;
  LPCSTR postheader = "Content-Type: application/x-www-form-urlencoded";
  int port = 80;

  hOpen = InternetOpen("SimplePost", INTERNET_OPEN_TYPE_PRECONFIG, 0, 0, 0);
  if(hOpen == NULL)  {
     return -1;
  }
  // "127.0.0.1"대신에 다운받을 화일이 있는 서버주소를 입력 
  hConnect = InternetConnect(hOpen, "127.0.0.1", port, 0, 0, INTERNET_SERVICE_HTTP, 0, 0);
  hReq = HttpOpenRequest(hConnect, "POST", "/test.bin", "HTTP/1.1", 0, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0);
  HttpSendRequest(hReq, postheader, lstrlen(postheader), NULL, 0);

  DWORD dwRead = 0;
  DWORD Size;
  CHAR Data[1025] = "";
  FileOpen("Filename");
  do 
  {     // 다운받는화일의 나머지 크기 얻어오기
     InternetQueryDataAvailable(hReq,&Size,0,0);     // 남은 크기가 1024보다 크면 1024로 고정
     if(Size>1024) Size = 1024;
     InternetReadFile(hReq, (LPVOID)Data, Size, &dwRead);
     if(dwRead) {
        Data[dwRead] = 0x00;
        FileWrite(Data, Size);
     }
  } while(dwRead != 0);  //읽어온 데이터의 크기가 0이 아니면 계속 반복

  FileClose();

  InternetCloseHandle(hConnect);
  InternetCloseHandle(hOpen);

  hConnect = NULL;
  hOpen = NULL;

// FileOpen(), FIleWrite(), FIleClose()함수 별도

Linux Xubuntu에 CommonAPI C/C++ 개발환경 구축하기

Xubuntu 16.04 환경(설치방법)에서 GENIVI의 CommonAPI C/C++ 개발 환경을 구축해 보자.
  • JAVA 설치(Version 8)
    • Oracle Site(www.oracle.com)에서 JAVA SE 8 8u161 다운로드
    • 다운로드페이지에서 Accept License Agreement 체크
    • 64bit 버젼 다운로드(jdk-8u161-linux-x64.tar.gz)
    • Xubuntu에 기본적으로 설치되어져있는 firefox에서 다운로드 받으면 ~/Downloads폴더에 저장된다.
    • Downloads 폴더로 이동후 압축을 해제한다.
      • $ tar -xvzf jdk-8u161-linux-x64.tar.gz
    • 관리자 권한으로 압축해제된 파일들을 /usr/local 폴더 아래로 이동시킨다.
      • $ sudo mv jdk1.8.0_161 /usr/local
    • 앞에서 설치한 파일들을 사용할 수 있도록 다음과 같이 환경 변수를 설정한다.
      • $ sudo vi /etc/profile
        • JAVA_HOME=/usr/local/jdk1.8.0_161
        • PATH=$PATH:$JAVA_HOME/bin
        • CLASS_PATH=.:$JAVA_HOME/jre/lib/ext:$JAVA_HOME/lib/tools.jar
        • export JAVA_HOME PATH CLASS_PATH
    • 다음과 같이 변경된 profile을 적용한다.
      • $ source /etc/profile

    • g++ Compiler를 설치 및 버젼 확인.
      • $ sudo apt-get install g++
      • $ g++ --version

    • cmake 설치 및 버젼 확인.
      • $ sudo apt-get install cmake
      • $ cmake --version

    • expat 설치
      • $ wget http://sourceforge.net/projects/expat/files/expat/2.1.0/expat-2.1.0.tar.gz
      • $ tar -xzf expat-2.1.0.tar.gz 
      • $ cd expat-2.1.0/
      • $ ./configure
      • $ make
      • $ sudo make install

    • CommonAPI 개발환경 구축 완료