Skip to content

Instantly share code, notes, and snippets.

@makerj
Last active March 16, 2018 05:23
Show Gist options
  • Select an option

  • Save makerj/9efe2fbf5ff0baba154493a7808629e3 to your computer and use it in GitHub Desktop.

Select an option

Save makerj/9efe2fbf5ff0baba154493a7808629e3 to your computer and use it in GitHub Desktop.

Revisions

  1. makerj revised this gist Mar 16, 2018. 1 changed file with 0 additions and 22 deletions.
    22 changes: 0 additions & 22 deletions SWIG C and JAVA.md
    Original file line number Diff line number Diff line change
    @@ -113,48 +113,26 @@ int 타입이 매개변수로 들어왔을 때, mylib_wrap.c에서 처리하는

    _

    `typemap(in) TYPE`에서 TYPE을 와일드카드처럼 어떤 타입이던지 매핑하고 싶은 경우 와일드카드 타입인 `SWIGTYPE`을 사용한다. 다음의 간단한 예제는 자동 생성되는 모든 타입의 Java 코드에 자신의 클래스명을 출력하는 foo 메소드를 추가하는 코드이다.







    ## SWIG 헤더



    SWIG는 다양한 헤더를 통해, 개발자가 필요로 할 것으로 에상하는 기능을 제공한다. C and JAVA 상황에서 유용한 헤더는 다음과 같다.

    * `%include <stdint.i>` C의 stdint와 같은 효과를 낸다.

    * `%include <typemaps.i>` 기초 자료형에 대해 INPUT, OUTPUT, INOUT 타입맵을 제공한다. 포인터 매개변수 형태로 값을 반환하는 라이브러리와 연동할 때 매우 유용하다

    * `%include <various.i>` char**, BYTE array타입을 지원한다



    ## 각 파일에 소스코드를 직접 추가하는 방법

    mylib.java

    ```
    %pragma(java) modulecode=%{
    /* comments on mylib.java */
    %}
    ```



    mylibJNI.java

    ```
    %pragma(java) jniclasscode=%{
    /* comments on mylibJNI.java */
    %}
    ```

    mylib_wrap.c
    ```
    %{
  2. makerj revised this gist Mar 16, 2018. 1 changed file with 9 additions and 20 deletions.
    29 changes: 9 additions & 20 deletions SWIG C and JAVA.md
    Original file line number Diff line number Diff line change
    @@ -115,19 +115,7 @@ _

    `typemap(in) TYPE`에서 TYPE을 와일드카드처럼 어떤 타입이던지 매핑하고 싶은 경우 와일드카드 타입인 `SWIGTYPE`을 사용한다. 다음의 간단한 예제는 자동 생성되는 모든 타입의 Java 코드에 자신의 클래스명을 출력하는 foo 메소드를 추가하는 코드이다.

    ```

    %typemap(javacode) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{

    public void foo() {

    System.out.println("$javaclassname");

    }

    %}

    ```



    @@ -152,27 +140,19 @@ SWIG는 다양한 헤더를 통해, 개발자가 필요로 할 것으로 에상
    mylib.java

    ```

    %pragma(java) modulecode=%{

    /* comments on mylib.java */

    %}

    ```



    mylibJNI.java

    ```

    %pragma(java) jniclasscode=%{

    /* comments on mylibJNI.java */

    %}

    ```

    mylib_wrap.c
    @@ -181,3 +161,12 @@ mylib_wrap.c
    /* cmments on mylib_wrap.c ! */
    %}
    ```

    GENERATED-TYPE.java
    ```
    %typemap(javacode) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{
    public void foo() {
    System.out.println("$javaclassname");
    }
    %}
    ```
  3. makerj revised this gist Mar 16, 2018. 1 changed file with 109 additions and 41 deletions.
    150 changes: 109 additions & 41 deletions SWIG C and JAVA.md
    Original file line number Diff line number Diff line change
    @@ -1,106 +1,177 @@
    SWIG C and JAVA
    # SWIG C and JAVA



    (작성중)



    SWIG는 기존에 작성된 C 또는 C++ 라이브러리를 다양한 언어에 포팅하는데 사용되는 도구이다. 이 글에서는 C 라이브러리를 JAVA와 연결하는데 필요한 정보를 정리한다. 이 글에서 C 라이브러리의 이름은 mylib 라고 가정한다.

    구현 흐름


    ## 구현 흐름



    mylib.c, mylib.h 작성 -> mylib.i SWIG 중간 언어 작성 -> mylib.i를 swig로 변환 -> libmylib.so 빌드 -> libmylib_java.so 빌드 -> Java에서 사용 및 테스트

    _

    흐름이 굉장히 길고, 한 프로세스는 이전 프로세스에 영향을 받는다. 따라서 mylib.h에 변경이 하나라도 생기면 나머지 모든 작업을 다시 테스트 해봐야 한다. **mylib.h에서 제공하는 API가 충분히 고정되었을 때** SWIG 컨버팅을 시작해야 한다.



    ## 모듈 작성 (mylib.i)

    언어간 연동을 위해 필요한 기본이 되는 단위인 모듈은 SWIG 중간 언어를 사용해서 작성한다. mylib.i 파일에 `%module mylib`이라고 작성하고, swig를 사용해 변환하면 다음과 같이 3개의 파일이 자동으로 생성된다.

    * mylib_wrap.c - JNI 코드 (내부 구현)

    * mylibJNI.java - Java Native를 정의한 보조 클래스 (내부 구현)

    * mylib.java - Java API를 정의한 클래스. 사용자는 이 Java 클래스를 사용한다.

    흐름이 굉장히 길고, 한 프로세스는 이전 프로세스에 영향을 받는다. 따라서 mylib.h에 변경이 하나라도 생기면 나머지 모든 작업을 다시 테스트 해봐야 한다. mylib.h에서 제공하는 API가 충분히 고정되었을 때 SWIG 컨버팅을 시작해야 한다.

    모듈 작성 (mylib.i)
    언어간 연동을 위해 필요한 기본이 되는 단위인 모듈은 SWIG 중간 언어를 사용해서 작성한다. mylib.i 파일에 %module mylib이라고 작성하고, swig를 사용해 변환하면 다음과 같이 3개의 파일이 자동으로 생성된다.

    mylib_wrap.c - JNI 코드 (내부 구현)
    ## common directive

    mylibJNI.java - Java Native를 정의한 보조 클래스 (내부 구현)

    mylib.java - Java API를 정의한 클래스. 사용자는 이 Java 클래스를 사용한다.

    common directive
    %inline %{ C_CODES %} mylib.i 파일과, mylibwrap.c 파일에 동시에 해당 코드를 작성한 것과 같은 효과를 낸다. %{ C_CODES %} 는 mylibwrap.c 파일에만 작성한 효과를 내므로, %inline 이 더 강력하다.
    * `%inline %{ C_CODES %}` mylib.i 파일과, mylib_wrap.c 파일에 동시에 해당 코드를 작성한 것과 같은 효과를 낸다. `%{ C_CODES %}` 는 mylib_wrap.c 파일에만 작성한 효과를 내므로, `%inline` 이 더 강력하다.

    %ignore SYMBOL_NAME 해당 심볼을 완전히 무시한다. ignore는 해당 심볼이 나타나기 전에 선언되어야 한다. 이미 해당 심볼을 파싱하고 난 다음에는 의미가 없다.
    * `%ignore SYMBOL_NAME` 해당 심볼을 완전히 무시한다. `ignore`는 해당 심볼이 나타나기 전에 선언되어야 한다. 이미 해당 심볼을 파싱하고 난 다음에는 의미가 없다.

    extend STRUCT_OR_CLASS_NAME { JAVA_CODES }; 해당 이름을 갖는 구조체나 클래스에 추가 메소드를 삽입한다. struct Foo를 대상으로 코드를 추가한 뒤, 생성된 Foo.java 파일을 열어보면 추가된 코드를 확인할 수 있다.
    * `extend STRUCT_OR_CLASS_NAME { JAVA_CODES };` 해당 이름을 갖는 구조체나 클래스에 추가 메소드를 삽입한다. `struct Foo`를 대상으로 코드를 추가한 뒤, 생성된 Foo.java 파일을 열어보면 추가된 코드를 확인할 수 있다.

    typemap directive
    기본형(Primitive Types)를 제외한 사용자 정의 타입들은 SWIG에서 정의한 것이 없다. 따라서 해당 타입들을 적절하게 사용하려면 직접 SWIG의 typemap 기능을 사용해서 해당 타입을 어떻게 다룰 지를 정해줘야 한다.


    typemap을 사용하면 해당 타입에 대한 완전한 제어를 할 수 있게 되지만 다음과 같은 위험이 있다.
    ## typemap directive

    개발자가 직접 C/C++ 연동 코드 일부를 작성해야 한다.

    개발자가 직접 연동 코드를 작성하기 때문에, JNI를 깊게 알아야 한다.

    조금이라도 잘못 작성하면 SWIG 전체 연동 코드를 망칠 수 있다.
    기본형(Primitive Types)를 제외한 사용자 정의 타입들은 SWIG에서 정의한 것이 없다. 따라서 해당 타입들을 적절하게 사용하려면 직접 SWIG의 `typemap` 기능을 사용해서 해당 타입을 어떻게 다룰 지를 정해줘야 한다.

    간단하게 정리한 typemap 디렉티브의 종류 (더 많지만 생략)
    _

    %typemap(jstype) PROTOTYPE "TYPENAME"; mylib.java에 나타날 타입
    `typemap`을 사용하면 해당 타입에 대한 완전한 제어를 할 수 있게 되지만 다음과 같은 위험이 있다.

    %typemap(jtype) PROTOTYPE "TYPENAME"; mylibJNI.java에 나타날 타입
    * 개발자가 직접 C/C++ 연동 코드 일부를 작성해야 한다.

    %typemap(jni) PROTOTYPE "TYPENAME"; mylib_wrap.c에 나타날 타입
    * 개발자가 직접 연동 코드를 작성하기 때문에, JNI를 깊게 알아야 한다.

    %typemap(in) (PROTOTYPE) { JNICODE }; mylib_wrap.c에 매개변수로 넘어온 jtype을 C 타입으로 변환하는 코드를 직접 작성하는데 사용
    * 조금이라도 잘못 작성하면 SWIG 전체 연동 코드를 망칠 수 있다.

    %typemap(argout) PROTOTYPE %{ JNICODE %}; mylib_wrap.c에 매개변수로 넘어온 jtype과 관련된 동작이 모두 끝난 부분에 추가될 C 코드

    %fragment("FRAGMENT_NAME", "header") { C_CODES } typemap에 반복적으로 사용될 코드를 묶고, 이름을 둬서 나중에 typemap을 적용할 때 참조할 수 있게 한다. typemap(in), typemap(varin) 처럼 같은 목적의 C 코드가 반복될 것으로 예상되는 부분에 활용.

    %apply TARGET_TYPE { CURRENT_TYPE } CURRENTTYPE으로 선언된 코드를 마치 TARGETTYPE으로 선언한 것과 같이 취급한다.

    typemap(in) TYPE
    %typemap(in)은 해당 타입을 C 타입으로 변환하는 방법을 지시하는데 사용된다.
    간단하게 정리한 `typemap` 디렉티브의 종류 (더 많지만 생략)

    * `%typemap(jstype) PROTOTYPE "TYPENAME";` mylib.java에 나타날 타입

    * `%typemap(jtype) PROTOTYPE "TYPENAME";` mylibJNI.java에 나타날 타입

    * `%typemap(jni) PROTOTYPE "TYPENAME";` mylib_wrap.c에 나타날 타입

    * `%typemap(in) (PROTOTYPE) { JNICODE };` mylib_wrap.c에 매개변수로 넘어온 jtype을 C 타입으로 변환하는 코드를 직접 작성하는데 사용

    * `%typemap(argout) PROTOTYPE %{ JNICODE %};` mylib_wrap.c에 매개변수로 넘어온 jtype과 관련된 동작이 모두 끝난 부분에 추가될 C 코드

    * `%fragment("FRAGMENT_NAME", "header") { C_CODES }` typemap에 반복적으로 사용될 코드를 묶고, 이름을 둬서 나중에 typemap을 적용할 때 참조할 수 있게 한다. `typemap(in), typemap(varin)` 처럼 같은 목적의 C 코드가 반복될 것으로 예상되는 부분에 활용.

    * `%apply TARGET_TYPE { CURRENT_TYPE }` CURRENT_TYPE으로 선언된 코드를 마치 TARGET_TYPE으로 선언한 것과 같이 취급한다.



    ### typemap(in) TYPE



    `%typemap(in)`은 해당 타입을 C 타입으로 변환하는 방법을 지시하는데 사용된다.

    _

    먼저 가장 간단한 예제는 다음과 같다.

    ```

    %typemap(in) int {

    $1 = $input;

    printf("Received an integer : %d\n", $1);

    }

    ```

    int 타입이 매개변수로 들어왔을 때, mylib_wrap.c에서 처리하는 방법을 지시했다. 코드가 뭘 하는지는 명확하므로 설명하지 않고, 새로 등장한 키워드를 정리한다.

    $1 매개변수는 jint로 넘어왔을 테니, 이를 담을 c타입을 선언한다
    * `$1` 매개변수는 jint로 넘어왔을 테니, 이를 담을 c타입을 선언한다

    $input 매개변수를 의미한다
    * `$input` 매개변수를 의미한다

    _

    typemap(in) TYPE에서 TYPE을 와일드카드처럼 어떤 타입이던지 매핑하고 싶은 경우 와일드카드 타입인 SWIGTYPE을 사용한다. 다음의 간단한 예제는 자동 생성되는 모든 타입의 Java 코드에 자신의 클래스명을 출력하는 foo 메소드를 추가하는 코드이다.
    `typemap(in) TYPE`에서 TYPE을 와일드카드처럼 어떤 타입이던지 매핑하고 싶은 경우 와일드카드 타입인 `SWIGTYPE`을 사용한다. 다음의 간단한 예제는 자동 생성되는 모든 타입의 Java 코드에 자신의 클래스명을 출력하는 foo 메소드를 추가하는 코드이다.

    ```

    %typemap(javacode) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{

    public void foo() {

    System.out.println("$javaclassname");

    }

    %}
    SWIG 헤더

    ```





    ## SWIG 헤더



    SWIG는 다양한 헤더를 통해, 개발자가 필요로 할 것으로 에상하는 기능을 제공한다. C and JAVA 상황에서 유용한 헤더는 다음과 같다.

    %include <stdint.i> C의 stdint와 같은 효과를 낸다.
    * `%include <stdint.i>` C의 stdint와 같은 효과를 낸다.

    * `%include <typemaps.i>` 기초 자료형에 대해 INPUT, OUTPUT, INOUT 타입맵을 제공한다. 포인터 매개변수 형태로 값을 반환하는 라이브러리와 연동할 때 매우 유용하다

    * `%include <various.i>` char**, BYTE array타입을 지원한다

    %include <typemaps.i> 기초 자료형에 대해 INPUT, OUTPUT, INOUT 타입맵을 제공한다. 포인터 매개변수 형태로 값을 반환하는 라이브러리와 연동할 때 매우 유용하다

    %include <various.i> char**, BYTE array타입을 지원한다

    각 파일에 소스코드를 직접 추가하는 방법
    ## 각 파일에 소스코드를 직접 추가하는 방법

    mylib.java

    ```

    %pragma(java) modulecode=%{

    /* comments on mylib.java */

    %}

    ```



    mylibJNI.java

    ```

    %pragma(java) jniclasscode=%{

    /* comments on mylibJNI.java */
    %}
    /* comments on mylibJNI.java */

    %}

    ```

    @@ -110,6 +181,3 @@ mylib_wrap.c
    /* cmments on mylib_wrap.c ! */
    %}
    ```


    출처: http://makerj.tistory.com/321 [CheatSheet]
  4. makerj created this gist Mar 16, 2018.
    115 changes: 115 additions & 0 deletions SWIG C and JAVA.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,115 @@
    SWIG C and JAVA
    (작성중)

    SWIG는 기존에 작성된 C 또는 C++ 라이브러리를 다양한 언어에 포팅하는데 사용되는 도구이다. 이 글에서는 C 라이브러리를 JAVA와 연결하는데 필요한 정보를 정리한다. 이 글에서 C 라이브러리의 이름은 mylib 라고 가정한다.

    구현 흐름
    mylib.c, mylib.h 작성 -> mylib.i SWIG 중간 언어 작성 -> mylib.i를 swig로 변환 -> libmylib.so 빌드 -> libmylib_java.so 빌드 -> Java에서 사용 및 테스트


    흐름이 굉장히 길고, 한 프로세스는 이전 프로세스에 영향을 받는다. 따라서 mylib.h에 변경이 하나라도 생기면 나머지 모든 작업을 다시 테스트 해봐야 한다. mylib.h에서 제공하는 API가 충분히 고정되었을 때 SWIG 컨버팅을 시작해야 한다.

    모듈 작성 (mylib.i)
    언어간 연동을 위해 필요한 기본이 되는 단위인 모듈은 SWIG 중간 언어를 사용해서 작성한다. mylib.i 파일에 %module mylib이라고 작성하고, swig를 사용해 변환하면 다음과 같이 3개의 파일이 자동으로 생성된다.

    mylib_wrap.c - JNI 코드 (내부 구현)

    mylibJNI.java - Java Native를 정의한 보조 클래스 (내부 구현)

    mylib.java - Java API를 정의한 클래스. 사용자는 이 Java 클래스를 사용한다.

    common directive
    %inline %{ C_CODES %} mylib.i 파일과, mylibwrap.c 파일에 동시에 해당 코드를 작성한 것과 같은 효과를 낸다. %{ C_CODES %} 는 mylibwrap.c 파일에만 작성한 효과를 내므로, %inline 이 더 강력하다.

    %ignore SYMBOL_NAME 해당 심볼을 완전히 무시한다. ignore는 해당 심볼이 나타나기 전에 선언되어야 한다. 이미 해당 심볼을 파싱하고 난 다음에는 의미가 없다.

    extend STRUCT_OR_CLASS_NAME { JAVA_CODES }; 해당 이름을 갖는 구조체나 클래스에 추가 메소드를 삽입한다. struct Foo를 대상으로 코드를 추가한 뒤, 생성된 Foo.java 파일을 열어보면 추가된 코드를 확인할 수 있다.

    typemap directive
    기본형(Primitive Types)를 제외한 사용자 정의 타입들은 SWIG에서 정의한 것이 없다. 따라서 해당 타입들을 적절하게 사용하려면 직접 SWIG의 typemap 기능을 사용해서 해당 타입을 어떻게 다룰 지를 정해줘야 한다.


    typemap을 사용하면 해당 타입에 대한 완전한 제어를 할 수 있게 되지만 다음과 같은 위험이 있다.

    개발자가 직접 C/C++ 연동 코드 일부를 작성해야 한다.

    개발자가 직접 연동 코드를 작성하기 때문에, JNI를 깊게 알아야 한다.

    조금이라도 잘못 작성하면 SWIG 전체 연동 코드를 망칠 수 있다.

    간단하게 정리한 typemap 디렉티브의 종류 (더 많지만 생략)

    %typemap(jstype) PROTOTYPE "TYPENAME"; mylib.java에 나타날 타입

    %typemap(jtype) PROTOTYPE "TYPENAME"; mylibJNI.java에 나타날 타입

    %typemap(jni) PROTOTYPE "TYPENAME"; mylib_wrap.c에 나타날 타입

    %typemap(in) (PROTOTYPE) { JNICODE }; mylib_wrap.c에 매개변수로 넘어온 jtype을 C 타입으로 변환하는 코드를 직접 작성하는데 사용

    %typemap(argout) PROTOTYPE %{ JNICODE %}; mylib_wrap.c에 매개변수로 넘어온 jtype과 관련된 동작이 모두 끝난 부분에 추가될 C 코드

    %fragment("FRAGMENT_NAME", "header") { C_CODES } typemap에 반복적으로 사용될 코드를 묶고, 이름을 둬서 나중에 typemap을 적용할 때 참조할 수 있게 한다. typemap(in), typemap(varin) 처럼 같은 목적의 C 코드가 반복될 것으로 예상되는 부분에 활용.

    %apply TARGET_TYPE { CURRENT_TYPE } CURRENTTYPE으로 선언된 코드를 마치 TARGETTYPE으로 선언한 것과 같이 취급한다.

    typemap(in) TYPE
    %typemap(in)은 해당 타입을 C 타입으로 변환하는 방법을 지시하는데 사용된다.


    먼저 가장 간단한 예제는 다음과 같다.

    %typemap(in) int {
    $1 = $input;
    printf("Received an integer : %d\n", $1);
    }
    int 타입이 매개변수로 들어왔을 때, mylib_wrap.c에서 처리하는 방법을 지시했다. 코드가 뭘 하는지는 명확하므로 설명하지 않고, 새로 등장한 키워드를 정리한다.

    $1 매개변수는 jint로 넘어왔을 테니, 이를 담을 c타입을 선언한다

    $input 매개변수를 의미한다


    typemap(in) TYPE에서 TYPE을 와일드카드처럼 어떤 타입이던지 매핑하고 싶은 경우 와일드카드 타입인 SWIGTYPE을 사용한다. 다음의 간단한 예제는 자동 생성되는 모든 타입의 Java 코드에 자신의 클래스명을 출력하는 foo 메소드를 추가하는 코드이다.

    %typemap(javacode) SWIGTYPE, SWIGTYPE &, SWIGTYPE *, SWIGTYPE [ANY] %{
    public void foo() {
    System.out.println("$javaclassname");
    }
    %}
    SWIG 헤더
    SWIG는 다양한 헤더를 통해, 개발자가 필요로 할 것으로 에상하는 기능을 제공한다. C and JAVA 상황에서 유용한 헤더는 다음과 같다.

    %include <stdint.i> C의 stdint와 같은 효과를 낸다.

    %include <typemaps.i> 기초 자료형에 대해 INPUT, OUTPUT, INOUT 타입맵을 제공한다. 포인터 매개변수 형태로 값을 반환하는 라이브러리와 연동할 때 매우 유용하다

    %include <various.i> char**, BYTE array타입을 지원한다

    각 파일에 소스코드를 직접 추가하는 방법
    mylib.java

    %pragma(java) modulecode=%{
    /* comments on mylib.java */
    %}
    mylibJNI.java

    ```

    %pragma(java) jniclasscode=%{

    /* comments on mylibJNI.java */
    %}


    ```

    mylib_wrap.c
    ```
    %{
    /* cmments on mylib_wrap.c ! */
    %}
    ```


    출처: http://makerj.tistory.com/321 [CheatSheet]