[Java] 어떻게하면 다른 언어 (예 : 파이썬)에 바인딩합니까 (예 : C ++)?


Answers

C89에 반영된 통역사, 누가 알았습니까?

API에 대한 링크 또는 코드 작성 방법에 대한 설명이 아닌 메커니즘에 대한 설명을 찾고 있다는 느낌이 들었습니다. 그래서, 그것을 이해합니다. . .

주 인터프리터는 일반적으로 C로 작성되며 동적으로 링크됩니다. 동적으로 링크 된 환경에서 C89조차도 어느 정도의 반사 동작을합니다. 특히 dlopen(3)dlsym(3) 호출은 동적 (일반적으로 ELF) 라이브러리를로드하고 문자열로 명명 된 심볼의 주소를 찾습니다. 해당 주소를 알려 주면 통역사가 기능을 호출 할 수 있습니다. 정적으로 링크 된 경우에도 인터프리터는 컴파일 된 C 함수의 주소를 알 수 있습니다.

그렇다면 인터프리터에게 인터프리터에게 특정 네이티브 라이브러리에서 특정 네이티브 함수를 호출하도록 통역 코드를 전달하는 것은 간단합니다.

메커니즘은 모듈 식일 수 있습니다. 스크립트로 작성된 인터프리터 용 확장 라이브러리는 dlopen(3)dlsym(3) 대한 기본 훅을 호출 할 수 있으며 인터프리터가 전혀 알지 못하는 새 라이브러리에 연결할 수 있습니다.

값으로 간단한 객체를 전달하기 위해 일반적으로 몇 가지 프로토 타입 함수가 다양한 호출을 허용합니다. 그러나 구조화 된 데이터 객체 (stat (2)를 상상해보십시오)의 경우 래퍼 모듈은 데이터의 레이아웃을 알아야합니다. 어떤 시점에서, 확장 모듈을 패키징하거나 설치할 때 C 인터페이스 모듈은 적절한 헤더 파일을 포함하고 필기 코드와 함께 인터페이스 객체를 구성합니다. 이것은 시스템에 sqlite3 이 이미 있더라도 libsqlite3-dev 와 같은 것을 설치해야하는 이유입니다. -dev 패키지에만 링키지 코드를 다시 컴파일하는 데 필요한 .h 파일이 있습니다.

나는 이것을 "짐승과 무지로 끝낸다" 고 말하면서 요약 할 수 있다고 생각합니다. :-)

Question

나는 파이썬 전문가와는 거리가 멀지 만 C / C ++ 바인딩에 관해서는 항상 이것을 듣는다. 이 개념은 어떻게 작동하며 Python (및 Java)은 OpenGL과 같은 C 기반 API에 어떻게 바인딩됩니까? 이 물건은 항상 나에게 수수께끼였다.




Perl의 경우 C ++ 서브 루틴을 호출하는 두 가지 방법이 있습니다.




일반적으로 이러한 언어에는 C로 작성된 확장을로드하는 방법이 있습니다. Java 인터페이스는 JNI (Java Native Interface)라고합니다. 파이썬에는 확장 인터페이스에 대한 포괄적 인 문서 가 있습니다.

파이썬을위한 또 다른 옵션은 사용자 정의 확장 코드를 작성하지 않고도 동적으로로드 할 수있는 C 라이브러리로 작업 할 수있게 해주는 ctypes 모듈입니다.




기본적으로 c / c ++와 python을 통합하는 두 가지 방법이 있습니다.

  • 확장 : 파이썬에서 c / c ++에 액세스하기
  • 임베딩 : c / c ++에서 파이썬 인터프리터에 액세스하기

당신이 언급 한 것은 첫 번째 경우입니다. 일반적으로 함수 인수 및 데이터 형식을 필요한 언어와 일치시키는 다른 언어 사이의 코드 로 사용되는 래퍼 함수 를 작성 하여이 기능 을 구현합니다. 보통이 접착제 코드를 생성하는 데 SWIG 도구가 사용됩니다.

자세한 설명은이 자습서를 참조하십시오.




주요 일반 개념은 FFI , "Foreign Function Interface"로 알려져 있습니다. Java는 JNI, Python은 "Python C API", Perl은 XS 등입니다. 더 철저하게 연구하는 데 도움이되는 예술 용어.

FFI가 주어지면 직접적으로 존중하는 C 프로그램을 작성할 수 있고 / 또는 다른 언어로 작성된 코드에서받은 메타 정보에서 이러한 C 코드를 생성하는 코드 생성기를 사용할 수 있습니다 (종종 도움이됩니다. 예를 들어 SWIG 코드 생성기를 구동하려면 일반적으로 .h C 헤더 파일에있는 정보를 꾸미십시오.

Cython 과 같은 특수 언어도 있습니다. 파이썬의 "확장 된 서브 세트"는 파이썬의 구문과 의미의 대부분과 일치하면서 FFI 코드를 쉽게 생성 할 수 있도록 만들어졌습니다. 대부분 파이썬 프로그래머가 파이썬 확장을 작성하는 가장 쉬운 방법 일 수 있습니다 모듈은 신속한 기계 코드로 컴파일되고 기존의 C 호출 가능 라이브러리를 사용할 수도 있습니다.

ctypes 접근 방식은 전통적인 "FFI"접근법과 다르지만 "Python 용 외부 함수 라이브러리"로 자체 기술합니다. DLL에서 사용할 수있는 외부 코드 (또는 이와 동등한 .so 동적 라이브러리)에서 의존합니다. 리눅스)를 생성하고 런타임에 코드를 생성하고 실행하여 동적으로로드 된 C 코드에 접근합니다 (일반적으로 파이썬에서 명시 적 프로그래밍을 통해 모두 수행됩니다 - 아직 내성 검사 및 ctypes 코드 생성을 기반으로하는 ctypes 래퍼를 알지 못합니다) . 핸디는 Python으로 기존 DLL에 액세스하는 간단한 작업을 위해 특별한 것을 설치하지 않아도되지만, FFI "링커 기반"접근법 (확장 런타임이 더 많이 필요함 등)뿐만 아니라 확장되지 않는다고 생각합니다. . 필자는 Python의 ctyp을 뛰어 넘는 다른 언어를 목표로하는 이러한 접근법을 구현하지 못했습니다. (현재 DLL과 .so 패키지가 널리 보급되어 있다고 생각합니다.




아래의 개념은 비교적 쉽게 일반화 될 수 있지만 명확하게하기 위해 C와 Python을 많이 언급하려고합니다.

파이썬에서 C 호출하기

대부분의 저수준 언어 / 아키텍처 / 운영 체제에는 응용 프로그램이 서로 상호 작용하는 방법과 운영 체제에 대한 모든 하위 수준 세부 정보를 지정하는 잘 정의 된 응용 프로그램 이진 인터페이스가 있기 때문에이 방법을 사용할 수 있습니다. 예를 들어 AMD64 용 ABI는 AMD64 System V Application Binary Interface 입니다. 함수에 대한 호출 규칙 및 C 오브젝트 파일에 대한 링크와 같은 모든 세부 사항을 지정합니다.

이 정보를 사용하면 언어 구현자가

  1. 전화하고자하는 언어의 ABI를 구현하십시오.

  2. 구현에 액세스 할 언어 / 라이브러리를 통한 인터페이스 제공

(1) 사실상 대부분의 언어에서 통역사 / 컴파일러가 C로 코딩 되었기 때문에 무료로 거의 무료로 제공됩니다. 이것은 C로 코딩되지 않은 언어의 구현에서 C 코드를 호출하는 데 어려움이있는 이유이기도합니다 (예 : IronPython (C #의 Python 구현) 및 PyPy (Python의 Python 구현)는 C 코드를 호출하는 데 특히 뛰어난 지원을하지 못합니다. IronPython에서 이와 관련하여 몇 가지 작업이 있었다고 생각하십시오.

그래서 이것을 구체적으로하기 위해 CPython (C에서 완성 된 Python의 표준 구현)이 있다고 가정 해 봅시다. 우리는 인터프리터가 C로 작성되어 있고 다른 C 프로그램 (dlopen, LoadLibrary, 뭐든간에)에서와 같은 방식으로 인터프리터에서 C 라이브러리에 액세스 할 수 있으므로 무료로 (1)을 얻습니다. 이제는 우리 언어로 작성하는 사람들이 이러한 시설에 액세스 할 수있는 방법을 제공해야합니다. Python은 Python C / C ++ API 또는 ctypes를 통해이를 수행 합니다. 프로그래머가 이러한 API를 사용하여 코드를 작성할 때마다 적절한 라이브러리로드 / 호출 코드를 실행하여 라이브러리를 호출 할 수 있습니다.

C에서 파이썬 호출하기

이 방향은 실제로 설명하기에 조금 더 간단합니다. 앞의 예에서 보았 듯이, 우리의 인터프리터 인 CPython은 C로 작성된 프로그램에 불과하므로 함수를 내보내고 C로 작성하려는 모든 프로그램에 의해 라이브러리로 컴파일되거나 링크 될 수 있습니다. CPython은 C 파이썬 프로그램에 액세스 / 실행하기위한 함수이며 우리는이 함수를 호출하여 우리 애플리케이션에서 파이썬 코드를 실행할 수 있습니다. 예를 들어 CPython 라이브러리에서 내 보낸 함수 중 하나는 다음과 같습니다.

PyObject* PyRun_StringFlags(const char *str, int start, PyObject *globals, PyObject *locals, PyCompilerFlags *flags

반환 값 : 새로운 참조.

flags로 지정된 컴파일러 플래그를 사용하여 사전 전역 변수 및 지역 변수로 지정된 컨텍스트에서 str의 Python 소스 코드를 실행합니다. 매개 변수 start는 소스 코드를 구문 분석하는 데 사용해야하는 시작 토큰을 지정합니다.

이 함수는 유효한 파이썬 코드 (및 실행에 필요한 다른 세부 사항)를 포함하는 문자열을 전달하여 파이썬 코드를 문자 그대로 실행할 수 있습니다. 자세한 내용 은 다른 응용 프로그램파이썬 포함 을 참조하십시오.