언어에 구애받지 않는 교차 플랫폼 컴퓨터 비전 SDK : 실습 자습서

(Cyrus Behroozi) (2020 년 10 월 21 일)

최근 Venice Computer Vision 모임에서 발표 할 기회가있었습니다. 익숙하지 않다면 Trueface 가 후원하는 이벤트로, 컴퓨터 비전 개발자와 애호가 모두 최첨단 컴퓨터 비전 연구, 응용 프로그램 및 실습을 선보일 수 있습니다. 자습서.

이 기사에서는 플랫폼 간 배포 및 최대 확장 성을 위해 언어에 구애받지 않는 컴퓨터 비전 소프트웨어 개발자 키트 (SDK)를 설계하는 방법에 대한 자습서 프레젠테이션을 살펴 보겠습니다. 프레젠테이션의 실시간 녹화 를 보려면 여기 . 또한 전체 프로젝트 오픈 소스 를 만들었으므로 다음 컴퓨터 비전 프로젝트의 템플릿으로 자유롭게 사용하십시오.

cyrusbehr / sdk_design

플랫폼 간 배포 및 최대 확장 성을 위해 언어에 구애받지 않는 SDK를 설계하는 방법. 베니스 컴퓨터 비전…

github.com

이 튜토리얼이 중요한 이유

내 경험상 모든 것을 포괄하는 가이드를 찾지 못했습니다. 언어에 구애받지 않는 크로스 플랫폼 SDK를 만드는 데 필요한 모든 관련 단계를 요약합니다. 적절한 정보를 얻기 위해 서로 다른 문서를 샅샅이 뒤지고, 각 구성 요소를 개별적으로 학습 한 다음, 모두 함께 조각화해야했습니다. 답답했습니다. 많은 시간이 걸렸습니다. 이제 독자 여러분, 제 모든 작업에서 혜택을 받으십시오. 앞서 언어에 구애받지 않는 교차 플랫폼 SDK를 빌드하는 방법을 배우게됩니다. 모든 필수 요소가 있습니다. 약간의 밈을 저장하십시오. 즐기십시오.

이 자습서에서 다음 방법을 배울 수 있습니다.

  • C ++로 기본 컴퓨터 비전 라이브러리 구축
  • 컴파일 및 교차- AMD64, ARM64 및 ARM32 용 라이브러리 컴파일
  • 라이브러리와 모든 종속성을 단일 정적 라이브러리로 패키징
  • 단위 테스트 자동화
  • 연속 통합 (CI) 파이프 라인
  • 라이브러리 용 Python 바인딩 작성
  • API에서 직접 문서 생성

이 데모를 위해 MTCNN이라는 오픈 소스 얼굴 감지기를 사용하여 얼굴 및 랜드 마크 감지 SDK를 빌드합니다.

예 얼굴 경계 상자 및 얼굴 랜드 마크

우리의 API 함수는 이미지 경로를 가져온 다음 얼굴 경계 상자와 얼굴 랜드 마크의 좌표를 반환합니다. 얼굴 인식 기능은 얼굴 인식, 연령 예측, 자동 얼굴 블러 링을 포함한 많은 파이프 라인의 첫 번째 단계이므로 컴퓨터 비전에서 매우 유용합니다.

참고 : 이를 위해 자습서, Ubuntu 18.04에서 작업 할 것입니다.

라이브러리에 C ++를 사용하는 이유는 무엇입니까?

효율적인 C ++ 코드 실행은 다음과 같이 느껴질 수 있습니다.

대부분의 라이브러리는 컴파일되고 정적으로 형식화 된 언어 인 C ++로 작성됩니다. C ++가 매우 빠른 프로그래밍 언어라는 것은 비밀이 아닙니다. 우리가 원하는 속도를 제공하고 최소한의 추가 런타임 오버 헤드를 갖기에 충분히 낮은 수준입니다.

컴퓨터 비전 애플리케이션에서 우리는 일반적으로 많은 이미지를 조작하고, 매트릭스 작업을 수행하고, 머신 러닝 추론을 실행합니다. 엄청난 양의 컴퓨팅. 따라서 실행 속도가 중요합니다. 이는 원하는 프레임 속도를 달성하기 위해 지연 시간을 줄여야하는 실시간 애플리케이션에서 특히 중요합니다. 종종 모든 코드를 실행하는 데 밀리 초 밖에 걸리지 않습니다.

C ++의 또 다른 장점은 특정 아키텍처에 대해 컴파일하고 모든 종속성을 정적으로 연결하면 추가 인터프리터 나 라이브러리없이 해당 하드웨어에서 실행할 수 있습니다. 믿거 나 말거나 운영 체제가없는 베어 메탈 임베디드 장치에서도 실행할 수 있습니다!

디렉터리 구조

프로젝트에 다음 디렉터리 구조를 사용할 것입니다.

디렉터리 구조

p>

3rdparty에는 프로젝트에 필요한 타사 종속성 라이브러리가 포함됩니다.

dist에는 SDK의 최종 사용자에게 배포되는 파일이 포함됩니다. 이 경우 라이브러리 자체와 관련 헤더 파일이됩니다.

docker에는 도커 이미지를 생성하는 데 사용될 도커 파일이 포함됩니다. CI 빌드를 위해.

docs에는 헤더 파일에서 직접 문서를 생성하는 데 필요한 빌드 스크립트가 포함됩니다.

include에는 공개 API 용 포함 파일이 포함됩니다.

models에는 얼굴 감지 딥 러닝 모델 파일이 포함됩니다.

python에는 Python 바인딩을 생성하는 데 필요한 코드가 포함됩니다.

src에는 컴파일 될 모든 cpp 파일이 포함됩니다. SDK와 함께 배포되지 않는 모든 헤더 파일 (내부 헤더 파일)도 있습니다.

test에는 단위 테스트가 포함됩니다.

tools에는 크로스 컴파일에 필요한 CMake 도구 모음 파일이 포함됩니다.

종속성 라이브러리 설치

이 프로젝트의 경우 타사 필요한 종속성 라이브러리는 경량 머신 러닝 추론 라이브러리 인 ncnn , OpenCV , 이미지 확대 라이브러리, Catch2 , 단위 테스트 라이브러리, 마지막으로 pybind11 , 라이브러리 파이썬 바인딩 생성에 사용됩니다. 처음 두 라이브러리는 독립형 라이브러리로 컴파일해야하는 반면, 나머지 두 라이브러리는 헤더 전용이므로 소스 만 필요합니다.

이러한 라이브러리를 프로젝트에 추가하는 한 가지 방법은 git 하위 모듈을 사용하는 것입니다. . 이 접근 방식은 효과가 있지만 개인적으로 소스 코드를 가져 와서 원하는 플랫폼 (여기서는 AMD64, ARM32 및 ARM64) 용으로 빌드하는 셸 스크립트를 사용하는 것을 좋아합니다.

다음은 그 예입니다. 이러한 빌드 스크립트는 다음과 같습니다.

스크립트는 매우 간단합니다. git 저장소에서 원하는 릴리스 소스 코드를 가져 오는 것으로 시작합니다. 다음으로 CMake를 사용하여 빌드를 준비한 다음 make가 호출되어 컴파일러가 소스 코드를 빌드하도록합니다.

AMD64 빌드와 ARM 빌드의 주요 차이점은 다음과 같습니다. ARM 빌드는 CMAKE_TOOLCHAIN_FILE라는 추가 CMake 매개 변수를 전달합니다. 이 인수는 빌드 대상 아키텍처 (ARM32 또는 ARM64)가 호스트 아키텍처 (AMD64 / x86_64)와 다르다는 것을 CMake에 지정하는 데 사용됩니다. 따라서 CMake는 선택한 도구 모음 파일에 지정된 교차 컴파일러를 사용하여 라이브러리를 빌드하도록 지시합니다 (이 자습서 뒷부분의 도구 모음 파일에 대한 자세한 내용). 이 셸 스크립트가 작동하려면 Ubuntu 컴퓨터에 적절한 크로스 컴파일러가 설치되어 있어야합니다. apt-get를 사용하여 쉽게 설치할 수 있으며 설치 방법에 대한 지침은 여기 에 나와 있습니다.

라이브러리 API

라이브러리 API는 다음과 같습니다.

저는 매우 창의적이기 때문에 SDK 이름을 MySDK로 지정했습니다. API에는 ErrorCode라는 열거 형이 있고 Point라는 구조체가 있으며 마지막으로 하나의 공개 멤버 함수가 있습니다. getFaceBoxAndLandmarks 이 튜토리얼의 범위에서는 SDK 구현에 대해 자세히 다루지 않을 것입니다. 요점은 OpenCV를 사용하여 이미지를 메모리로 읽은 다음 오픈 소스 모델과 함께 ncnn을 사용하여 기계 학습 추론을 수행하여 얼굴 경계 상자와 랜드 마크를 감지한다는 것입니다. 구현에 대해 자세히 알아 보려면 여기 에서 수행 할 수 있습니다.

하지만주의를 기울이 셨으면하는 것은 우리가 사용하고있는 디자인 패턴. 우리는 기본적으로 별도의 클래스에 배치하여 클래스의 구현 세부 사항을 제거하는 구현 포인터 또는 pImpl 이라는 기술을 사용하고 있습니다. 위 코드에서 이는 Impl 클래스를 정방향으로 선언 한 다음이 클래스에 대한 unique_ptr를 개인 멤버 변수로 사용하여 수행됩니다. 그렇게함으로써 최종 사용자 (상업용 SDK에서 매우 중요 할 수 있음)의 눈에 띄지 않도록 구현을 숨길뿐만 아니라 API 헤더가 의존하는 헤더 수를 줄여서 #include ing 종속성 라이브러리 헤더의 API 헤더).

모델 파일에 대한 참고 사항

우리는 더 이상 다루지 않을 것이라고 말했습니다. 구현의 세부 사항이지만 언급 할 가치가 있다고 생각하는 것이 있습니다. 기본적으로 우리가 사용하는 오픈 소스 얼굴 감지기 인 MTCNN은 런타임에 기계 학습 모델 파일을로드합니다. 최종 사용자에게 모델을 배포해야하기 때문에 이상적이지 않습니다. 이 문제는 사용자가 이러한 모델 파일에 무료로 액세스하는 것을 원하지 않는 상용 모델에서 더욱 중요합니다 (이러한 모델을 교육하는 데 많은 시간이 소요 된 것을 생각해보십시오). 한 가지 해결책은 이러한 모델의 파일을 암호화하는 것입니다.그러나 이는 여전히 SDK와 함께 모델 파일을 제공해야 함을 의미합니다. 궁극적으로 우리는 사용자가 소프트웨어를 더 쉽게 사용할 수 있도록 사용자에게 보내는 파일의 수를 줄이고 싶습니다 (파일 수가 적을수록 잘못된 위치가 적어짐). 따라서 아래 표시된 방법을 사용하여 모델 파일을 헤더 파일로 변환하고 실제로 SDK 자체에 임베드 할 수 있습니다.

xdd bash 명령은 16 진 덤프를 생성하는 데 사용되며 이진 파일에서 헤더 파일을 생성하는 데 사용할 수 있습니다. 따라서 일반 헤더 파일처럼 코드에 모델 파일을 포함하고 메모리에서 직접로드 할 수 있습니다. 이 접근 방식의 한계는 컴파일 타임에 너무 많은 메모리를 사용하기 때문에 매우 큰 모델 파일에서는 실용적이지 않다는 것입니다. 대신 ld와 같은 도구를 사용하여 이러한 대형 모델 파일을 개체 파일로 직접 변환 할 수 있습니다.

CMake 및 라이브러리 컴파일

이제 CMake를 사용하여 프로젝트의 빌드 파일을 생성 할 수 있습니다. 익숙하지 않은 경우 CMake는 빌드 프로세스를 관리하는 데 사용되는 빌드 시스템 생성기입니다. 아래에서 루트 CMakeLists.txt (CMake 파일)의 모양을 확인할 수 있습니다.

기본적으로 구현 된 두 개의 소스 파일 인 my_sdk.cpp<이 포함 된 my_sdk_static라는 정적 라이브러리를 만듭니다. / div> 및 mtcnn.cpp 우리가 정적 라이브러리를 만드는 이유는 내 경험상 정적 라이브러리를 사용자에게 배포하는 것이 더 쉽고 임베디드 장치에 더 친숙하기 때문입니다. 위에서 언급했듯이 실행 파일이 정적 라이브러리에 연결되어 있으면 운영 체제가없는 임베디드 장치에서도 실행할 수 있습니다. 이것은 단순히 동적 라이브러리로는 불가능합니다. 또한 동적 라이브러리를 사용하면 종속성 버전에 대해 걱정해야합니다. 라이브러리와 관련된 매니페스트 파일이 필요할 수도 있습니다. 정적으로 링크 된 라이브러리는 또한 동적 라이브러리보다 약간 더 나은 성능 프로필을 가지고 있습니다.

CMake 스크립트에서 다음으로 할 일은 소스 파일에 필요한 포함 헤더 파일을 찾을 위치를 CMake에 알리는 것입니다. 참고할 사항 :이 시점에서 라이브러리가 컴파일되지만 라이브러리에 대한 링크 (예 : 실행 파일 사용)를 시도하면 심볼 오류에 대한 정의되지 않은 참조가 절대적으로 많이 발생합니다. 이는 종속성 라이브러리를 연결하지 않았기 때문입니다. 따라서 실행 파일을 libmy_sdk_static.a에 성공적으로 연결하려면 모든 종속성 라이브러리 (OpenCV 모듈, ncnn 등)도 추적하고 연결해야합니다. 동적 라이브러리와 달리 정적 라이브러리는 자체 종속성을 해결할 수 없습니다. 기본적으로 아카이브로 패키징 된 개체 파일 모음 일뿐입니다.

이 자습서의 뒷부분에서 모든 종속성 라이브러리를 정적 라이브러리에 번들로 묶어 사용자가 필요하지 않게하는 방법을 보여 드리겠습니다. 종속성 라이브러리에 대한 링크에 대해 걱정하세요.

라이브러리 및 도구 모음 파일의 크로스 컴파일

엣지 컴퓨팅은 매우… 초초

많은 컴퓨터 비전 애플리케이션이 엣지에 배포됩니다. 일반적으로 일반적으로 ARM CPU가있는 저전력 임베디드 장치에서 코드를 실행하는 것이 포함됩니다. C ++는 컴파일 된 언어이기 때문에 애플리케이션이 실행될 CPU 아키텍처에 대한 코드를 컴파일해야합니다 (각 아키텍처는 서로 다른 어셈블리 명령어를 사용함).

자세히 알아보기 전에 ARM32와 ARM64의 차이점 (AArch32 및 AArch64라고도 함) AArch64는 ARM 아키텍처의 64 비트 확장을 나타내며 CPU 및 운영 체제에 따라 다릅니다. 예를 들어 Raspberry Pi 4에는 64 비트 ARM CPU가 있지만 기본 운영 체제 인 Raspbian은 32 비트입니다. 따라서 이러한 장치에는 AArch32 컴파일 바이너리가 필요합니다. 이 Pi 장치에서 Gentoo 와 같은 64 비트 운영 체제를 실행하려면 AArch64 컴파일 바이너리가 필요합니다. 널리 사용되는 임베디드 장치의 또 다른 예는 온보드 GPU가 있고 AArch64를 실행하는 NVIDIA Jetson입니다.

크로스 컴파일하려면 CMake에 아키텍처 용으로 컴파일하지 않음을 지정해야합니다. 우리가 현재 만들고있는 기계. 따라서 CMake가 사용해야하는 크로스 컴파일러를 지정해야합니다. AArch64의 경우 aarch64-linux-gnu-g++ 컴파일러를 사용하고 AArch32의 경우 arm-linux-gnuebhif-g++ 컴파일러를 사용합니다 (hf는 hard float ).

다음은 도구 모음 파일의 예입니다. 보시다시피 AArch64 크로스 컴파일러를 사용하도록 지정하고 있습니다.

루트 CMakeLists.txt로 돌아 가면 파일 상단에 다음 코드를 추가합니다.

기본적으로 CMake 옵션을 추가합니다. 크로스 컴파일을 위해 명령 줄에서 활성화 할 수 있습니다. BUILD_ARM32 또는 BUILD_ARM64 옵션을 사용하면 적절한 도구 모음 파일이 선택되고 교차 컴파일을위한 빌드가 구성됩니다.

종속성 라이브러리를 사용하여 SDK 패키징

앞서 언급했듯이 개발자가이 시점에서 라이브러리에 연결하려는 경우 모든 기호를 해결하기 위해 모든 종속성 라이브러리에 대해서도 연결해야합니다. 종속성 라이브러리. 우리 앱은 매우 간단하지만 이미 8 개의 종속성 라이브러리가 있습니다! 첫 번째는 ncnn이고 그 다음에는 OpenCV 모듈 라이브러리가 3 개 있고 OpenCV (libjpeg, libpng, zlib, libtiff)로 빌드 된 4 개의 유틸리티 라이브러리가 있습니다. 사용자가 종속성 라이브러리를 직접 빌드하거나 라이브러리와 함께 제공하도록 요구할 수 있지만 궁극적으로 사용자를 위해 더 많은 작업이 필요하고 사용 장벽을 낮추는 것입니다. 이상적인 상황은 표준 시스템 라이브러리를 제외한 모든 타사 종속성 라이브러리와 함께 라이브러리가 포함 된 단일 라이브러리를 사용자에게 제공 할 수있는 경우입니다. CMake 마법을 사용하여이 작업을 수행 할 수 있습니다.

먼저 사용자 지정 대상을 CMakeLists.txt 그런 다음 MRI 스크립트를 실행합니다. 이 MRI 스크립트는 기본적으로 모든 정적 라이브러리를 단일 아카이브로 결합하는 ar -M bash 명령에 전달됩니다. 이 방법의 멋진 점은 원본 아카이브에서 겹치는 멤버 이름을 정상적으로 처리하므로 충돌에 대해 걱정할 필요가 없다는 것입니다. 이 사용자 지정 대상을 빌드하면 모든 종속성 아카이브와 함께 SDK를 포함하는 libmy_sdk.a가 생성됩니다.

잠시만 기다려주십시오. 지금까지했습니다.

숨을 쉬세요. 간식을 드세요. 엄마에게 전화하세요.

이 시점에서 우리는 SDK를 포함하는 libmy_sdk.a라는 정적 라이브러리가 있습니다. 단일 아카이브로 패키징 한 모든 종속성 라이브러리. 또한 모든 대상 플랫폼에 대해 컴파일 및 교차 컴파일 (명령 줄 인수 사용) 할 수 있습니다.

단위 테스트

처음으로 단위 테스트를 실행할 때

필요하지 않을 수도 있습니다. 단위 테스트가 중요한 이유를 설명하지만 기본적으로 개발자가 SDK가 들여 쓰기로 작동하는지 확인할 수 있도록하는 SDK 설계의 중요한 부분입니다. 또한 주요 변경 사항이 행 아래에있는 경우이를 추적하고 수정 사항을 더 빠르게 푸시하는 데 도움이됩니다.

이 특정 경우에 단위 테스트 실행 파일을 생성하면 의도 한대로 올바르게 링크 할 수 있도록 방금 만든 결합 라이브러리입니다 (그리고 정의되지 않은 기호에 대한 참조 오류가 발생하지 않음).

우리는 단위 테스트 프레임 워크로 Catch2를 사용하고 있습니다. . 구문은 다음과 같습니다.

Catch2가 작동하는 방식은 TEST_CASESECTION라는 다른 매크로. 각 SECTION에 대해 TEST_CASE는 처음부터 실행됩니다. 따라서이 예에서는 mySdk가 먼저 초기화 된 다음 비 얼굴 이미지라는 첫 번째 섹션이 실행됩니다. 다음으로 mySdk가 재구성되기 전에 분해 된 다음 “Faces in image”라는 두 번째 섹션이 실행됩니다. 이는 각 섹션에 대해 작업 할 새로운 MySDK 개체가 있는지 확인하기 때문에 좋습니다. 그런 다음 REQUIRE와 같은 매크로를 사용하여 어설 션을 만들 수 있습니다.

CMake를 사용하여 . 아래 3 행의 target_link_libraries 호출에서 볼 수 있듯이 연결해야하는 유일한 라이브러리는 libmy_sdk.a이며 다른 라이브러리는 없습니다. 종속성 라이브러리.

문서

사용자 만 문서를 읽을 수만 있다면

doxygen 은 헤더 파일에서 직접 문서를 생성합니다. 계속해서 아래 코드 스 니펫에 표시된 구문을 사용하여 공개 헤더에 모든 메소드와 데이터 유형을 문서화 할 수 있습니다.모든 함수에 대한 모든 입력 및 출력 매개 변수를 지정해야합니다.

실제로 문서를 생성하려면 , 기본적으로 문서를 생성하는 방법을 doxygen에 지시하는 청사진 인 doxyfile이라는 것이 필요합니다. 시스템에 doxygen이 설치되어 있다고 가정하고 터미널에서 doxygen -g를 실행하여 일반 doxyfile을 생성 할 수 있습니다. 다음으로 doxyfile을 편집 할 수 있습니다. 최소한 출력 디렉터리와 입력 파일도 지정해야합니다.

경우에, 우리는 API 헤더 파일에서 문서를 생성하기를 원하기 때문에 include 디렉토리를 지정했습니다. 마지막으로 CMake를 사용하여 실제로 문서를 빌드합니다. 그렇게 수행 할 수 있습니다.

Python 바인딩

아직 관련성이 낮은 gif를 보는 데 지쳤습니까? 예, 저도 마찬가지입니다.

솔직히 말씀 드리겠습니다. C ++는 개발하기 가장 쉽고 친숙한 언어가 아닙니다. 따라서 개발자가보다 쉽게 ​​사용할 수 있도록 언어 바인딩을 지원하도록 라이브러리를 확장하고자합니다. 인기있는 컴퓨터 비전 프로토 타이핑 언어 인 python을 사용하여이를 시연 할 것이지만 다른 언어 바인딩도 작성하기 쉽습니다. 이를 위해 pybind11을 사용하고 있습니다.

매크로는 파이썬 내에서 import 문이 실행될 때 호출 될 함수를 생성합니다. 따라서 위의 예에서 Python 모듈 이름은 mysdk입니다. 다음으로 pybind11 구문을 사용하여 클래스와 해당 멤버를 정의 할 수 있습니다.

다음 사항에 유의할 사항이 있습니다. C ++에서는 읽기 및 쓰기 액세스를 모두 허용하는 가변 참조를 사용하여 변수를 전달하는 것이 일반적입니다. 이것이 바로 faceDetectedfbAndLandmarks 매개 변수를 사용하여 API 멤버 함수로 수행 한 작업입니다. 파이썬에서는 모든 인수가 참조로 전달됩니다. 그러나 bool를 비롯한 특정 기본 Python 유형은 변경할 수 없습니다. 공교롭게도 faceDetected 매개 변수는 가변 참조에 의해 전달되는 부울입니다. 따라서 우리는 파이썬 래퍼 함수 내에서 bool을 정의하는 31-34 행에서 위의 코드에 표시된 해결 방법을 사용해야합니다. 그런 다음 튜플의 일부로 변수를 반환하기 전에이를 C ++ 함수에 전달해야합니다.

python 바인딩 라이브러리를 구축했으면 아래 코드를 사용하여 쉽게 활용할 수 있습니다.

지속적 통합

지속적 통합 파이프 라인의 경우 Github와 직접 통합되기 때문에 정말 좋아하는 CircleCI라는 도구를 사용할 것입니다. 커밋을 푸시 할 때마다 새 빌드가 자동으로 트리거됩니다. 시작하려면 CircleCI 웹 사이트 로 이동하여 Github 계정에 연결 한 다음 추가 할 프로젝트를 선택합니다. 추가 한 후에는 프로젝트 루트에 .circleci 디렉터리를 만들고 해당 디렉터리 내에 config.yml라는 파일을 만들어야합니다.

익숙하지 않은 사용자를 위해 YAML은 구성 파일에 일반적으로 사용되는 직렬화 언어입니다. 이를 사용하여 CircleCI가 수행 할 작업을 지시 할 수 있습니다. 아래 YAML 스 니펫에서 먼저 종속성 라이브러리 중 하나를 빌드하고 다음으로 SDK 자체를 빌드하고 마지막으로 단위 테스트를 빌드하고 실행하는 방법을 확인할 수 있습니다.

우리가 지능적이라면 (그리고 지금까지 해보 셨다고 가정합니다) 캐싱을 사용하여 빌드 시간을 크게 줄일 수 있습니다. 예를 들어, 위의 YAML에서 빌드 스크립트의 해시를 캐시 키로 사용하여 OpenCV 빌드를 캐시합니다. 이렇게하면 빌드 스크립트가 수정 된 경우에만 OpenCV 라이브러리가 다시 빌드됩니다. 그렇지 않으면 캐시 된 빌드가 사용됩니다. 주목해야 할 또 다른 사항은 선택한 도커 이미지 내부에서 빌드를 실행하고 있다는 것입니다. 모든 시스템 종속성을 설치 한 사용자 정의 Docker 이미지 ( 여기 는 Dockerfile입니다)를 선택했습니다.

Fin.

그리고 있습니다. 잘 설계된 다른 제품과 마찬가지로 우리는 가장 수요가 많은 플랫폼을 지원하고 가장 많은 개발자가 쉽게 사용할 수 있도록 만들고 싶습니다. 위의 자습서를 사용하여 여러 언어로 액세스 할 수 있고 여러 플랫폼에 배포 할 수있는 SDK를 구축했습니다. pybind11에 대한 문서를 직접 읽을 필요도 없습니다. 이 튜토리얼이 유용하고 재미 있었기를 바랍니다. 행복한 건물입니다.

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다