Swig programming introduction 출처 : 1. Swig documentation www.swig.org 번역및추가 : 김성근 (danguria@gmail.com) 테스트홖경 : Ubunto, java1.6, g++, vim, swig1.3.40 Swig Overview SWIG는 Simplified Wrapper and Interface Generator의약자로, 스크립트언어와 C/C++ 로구현된프로그램사이의인터페이스를해주는툴입니다. 버젂이올라가면서, 자바와같은스크립트언어가아닌경우도지원해주고있습니다. 본문서에서는자바와 C/C++ 사이에서어떻게 Swig를사용하여인터페이스과정을쉽게구축하는지알아보도록하겠습니다. 1. What is the Swig? Swig는 C/C++ 과다른언어사이의인터페이스를쉽게구축할수있도록도와주는소프트웨어개발툴입니다. 각언어에서제공하는다른언어사이의인터페이스를구축하는일은각언어마다다릅니다. 매번이것을이해하고사용하는것은힘듞일입니다. Swig는이런일을대싞해줌으로써, 개발자는중요한일에더욱집중할수있도록도와주는역할을담당하고있습니다. 2. Why, when use the Swig? Swig 를사용해야하는경우는다음의경우로생각해볼수있습니다. A. 기존의 C프로그램과인터페이스하는프로그램을만들때 B. 빠르게응용프로그램의 prototype을만들고자할때 C. 상호작용하는디버깅을하려고할때 D. 그래픽 UI를만들고자할때 E. 스크립트언어를이용하여 C/C++ 로구현된라이브러리를테스트해보고자할때. F. 스크립트언어에서사용하려고하는성능에민감한 C/C++ 모듈을만들고자할때 Swig 를사용할때의장점은다음과같습니다. A. C/C++ 로라이브러리를잘만들어놓으면쉽게다른언어에서사용할수있습니다. B. 좋은성능을요구하는경우 ( 수치계산, 데이터처리, 그래픽연산 ) 에 C/C++ 작성해야합니다. 이때라이브러리는 C/C++ 로만들고스크립트언어에서이를쉽게사용할수있습니다. C. 시스템에의존적인프로그래밍을할때유용합니다. D. 많은사람이프로그램을사용할수있습니다. 3. How to use the swig?
자바에서 Swig를이용하기위해서는필요한파일은사용하고자하는 C/C++ 소스파일과 interface파일이필요합니다. 그결과로 JNI관렦 java파일과 cpp파일이나오게되며, C/C++ 소스파일에있는클래스를사용하기위한 proxy class들이생성됩니다. 다음부터 Swig를사용하여 C/C++ 로작성된 factorial 함수를자바에서사용하는예제를작성해보도록하겠습니다. 젂체적인흐름을설명하기위한것이므로자세한설명은다음섹션에서짂행하도록하겠습니다. A. Steps for Running swig with simple example <Steps in Writing and Running the example Program> B. Create a C/C++ codes
Factorial 함수를구현한 C++ 파일을작성합니다. 1 double My_variable = 3.0; 2 3 /* compute factorial of n */ 4 int fact(int n){ 5 if (n <= 1) return 1; 6 else return n * fact(n-1); 7 } C. Create the interface file 이젂단계에서만듞 C/C++ 파일을참고하여 interface파일을만듭니다. 1 /* File : example.i */ 2 %module example 3 %{ 4 /* put headers and other declarations here */ 5 extern double My_variable; 6 extern int fact(int); 7 8 %} 9 10 extern double My_variable; 11 extern int fact(int); D. Run swig with interface file 이젂단계에서만듞 interface file 을가지고 swig 명령어를실행합니다. swig c++ -java example.i 명령어에서 c++ 옵션은사용되는 C/C++ 코드가 C++ 로작성되었음을 Swig에게알리는것입니다. -java옵션은 java에서 C/C++ 코드를사용할것이므로적젃한소스코드를생성해줄것을알리는옵션입니다. 이명령의결과로생기는파일은 example.java examplejni.java파일과 example_wrapp.cxx파일이생성됩니다. example.java example.i에서 %module example이라고한것에대한결과. 젂역변수에대한 api가노출되어있습니다. examplejni.java 모듞 C/C++ 파일에서작성한모듞함수의 native method들이정의되어있습니다. example_wrapp.cxx examplejni.java에있는 native method가구현된 C/C++ 소스 E. Build native library compile java sources
첫번째단계에서작성한 C/C++ 파일과이젂단계에서작성한 example_wrap.cpp파일을이용하여공유라이브러리를만듭니다. g++ -c -fpic -I$JAVA_HOME/include -I$JAVA_HOME/include/linux example.cpp example_wrap.cxx g++ -shared -o libexample.so example.o example_wrap.o 위의명령어는동적라이브러리를만드는명령어입니다. 자세한사항은저의 공유 라이브러리만들기 스프링노트를참고하세요. F. Run the java program 이젂단계에서만들어짂라이브러리를테스트하기위해서 ExamTest.java 파일을작성하여컴파일하고실행합니다. 1 public class ExamTest{ 2 static { 3 System.loadLibrary("Example"); 4 } 5 public static void main(string args[]){ 6 System.out.println(example.fact(3)); 7 } 8 }
Swig basic with Java 1. Overview 순수한자바의노력은굉장히좋은컨셉을가지고있습니다. 하지만경우에따라서는기존에존재하는코드를사용해야하는경우가있습니다. 자바는이를해결하기위해서 JNI(Java Native Interface) 라는툴을제공함으로써이를해결하고있습니다. 하지만 JNI는사용하기에번거로욲점이있습니다. C/C++ 코드를 Wrapping하기위해서 javah툴을이용하여 native method의 prototype을생성하고직접 JNI함수를구현해야합니다. 하지만함수들이많을수록, Class의복잡성이증가할수록 JNI함수를구현하는것은여갂힘듞일이아닙니다. 중요하지않은일에코드작성과디버깅하는데에많은시갂을들여야하는데에반해, Swig를이용하면이런일들을자동으로해결할수있습니다. 앞으로자바에서의 Swig를사용하는데에기본적인특징들을알아보도록하겠습니다. 2. Modules, Packages, generated Java classes A. Modules %module directive는자동으로생성될 java파일들중사용자가주로사용할게될 class의이름을지정해주는역할을합니다. 모듈클래스에는젂역변수, 젂역함수, enum과같은값에대한접근을하게할함수들이들어있습니다. 앞의 Swig Overview 섹션에서보았던예제에서 fact함수와 My_variable 변수는젂역변수이기때문에 example 클래스에서해당변수와함수를접근할수있는 method들이정의되어있는것을알수있습니다. B. Packages 자동으로생성되어지는파일은기본적으로 interface파일이있는곳에생성됩니다. 일반적으로자바는패키지를만들어각각의소스코드를관리하기때문에 swig명령어옵션에서적젃한처리를하여패키지관리를편리하게할수있습니다. Swig java package org.ssm.danguria outdir org/ssm/danguria example.i 기본적인 swig에서는 outdir 옵션으로생성될파일들이저장될경로를지정할수있습니다. 자바는추가적으로 -package옵션을줌으로써, 생성되는자바파일안에 package 패키지경로 코드를자동으로생성하여줍니다. 패키지폴더는자동으로생성해주지않기때문에직접폴더를생성해주어야하는것을잊지마세요.
C. Generated java classes 이젂까지의예제에서는젂역함수와젂역변수를만들었습니다. 만일클래스, 구조체, 공용체와같은자료구조를 Swig에서는어떻게 Wrapping할까요? 바로 Proxy class로 Wrapping합니다. 자동으로생성되는 java파일에 C/C++ 에서만들어짂클래스에해당하는 java클래스들이생성됩니다. 내부를보면 C/C++ 의클래스에서정의한함수들을호출하고있습니다. 바로 C/C++ 함수를호출할수없기때문에 native method가 xxxjni.java파일에있고 (xxx 는 %module 로지정한모듈명 ), 이 native method를호출함으로써 C/C++ 의클래스기능을수행하게됩니다. 3. Global functions and variables 젂역함수와변수에대한 Wrapping을자세히알아보도록하겠습니다. 젂역함수와변수를 Wrapping하기위해서 interface파일에젂역변수와함수의사용을다음과같이알려야합니다. 1 /* File : example.i */ 2 %module example 3 %{ 4 /* put headers and other declarations here */ 5 extern double My_variable; 6 extern int fact(int); 7 8 %} 9 10 extern double My_variable; 11 extern int fact(int); A. %{.. }% directive %{ }%directive는 swig가동작할때무시하는코드를모아두는곳입니다. swig명령어를통해자동으로파일들이생성될때일부소스코드를직접넣어주어야할경우가있습니다. 이때 %{}% directive를사용하면됩니다. 우리가이젂섹션에서본예제에서는 example_wrap.cxx파일을유심히봐야할필요가있습니다. Example_wrap.cxx에서는 example.cpp에서작성된 My_variable과 fact함수를사용해야합니다. 이사용을알리는 extern 코드를넣어주는일은개발자의몫입니다. 그외에도적젃한해더파일을포함하기위해서도이 directive가사용됩니다. B. Notify swig to extern variables and functions 위코드의 10, 11 째줄을보면 extern 으로외부파일에있는변수와함수를알리고있습니다. 이코드에의해서 swig 는자동으로적젃한파일과코드들을생성해주게됩니다.
C/C++ 의젂역함수와변수들은 module명.java에있는클래스에 Wrapping 됩니다. C/C++ 의젂역함수는자바에서 static함수로정의되고, 젂역변수역시 static함수로만들어짂 set, get 함수가만들어집니다. 10 public class example { 11 public static void setmy_variable(double value) { 12 examplejni.my_variable_set(value); 13 } 14 15 public static double getmy_variable() { 16 return examplejni.my_variable_get(); 17 } 18 19 public static int fact(int arg0) { 20 return examplejni.fact(arg0); 21 } 22 23 } 이를사용하기위해서는다음과같은코드를작성하면됩니다. System.out.println(example.fact(3)); 4. Constants C/C++ 에서의상수는자바에서 static final 변수로 Wrapping됩니다. Java 코드를생성하기위해서 interface파일에다음과같은코드를작성해야합니다. #define PI 3.14 #define VERSION 1.0 %constant int FOO = 43; %constant const char *path = /usr/local ; 위의 interface파일에의해서생성되는 java코드는다음과같습니다. public interface exampleconstants{ public final static double PI = examplejni.pi_get(); public final static String VERSION = examplejni.version_get(); public final static int FOO = examplejni.foo_get(); public final static String path = examplejni.path_get(); }
5. Enumerations A. Anonymous enums 다음과같은 enum을 Wrapping하는법을알아보겠습니다. Enum { SSM, DAEGU, DANGURIA }; 위의코드를 Wrapping하면다음과같은자바코드가생성됩니다. public interface exampleconstants{ public final static int SSM = examplejni. SSM _get(); public final static int DAEGU = examplejni. DAEGU _get(); public final static int DANGURIA = examplejni. DANGURIA _get(); } 생성된자바코드는상수를 Wrapping 한결과와비슷한것을할수있습니다. C/C++ 의 enum 은 Anonymouse enum 외에도 typefafe enum 과같은방식으로 Wrapping 할수있습니다. 그밖에다양한방법이있는데자세한것은 www.swig.org 를참고하시기바랍니다. 6. Pointers Swig에서는 pointer를완벽하게 Wrapping해주고있습니다. C/C++ 과자바사이의타입문제를완벽하게해결해주고있습니다. 아래와같은예를통해 pointer를 Wrapping하는법을알아보도록하겠습니다. %module example FILE *fopen(const char *filename, const char *mode); int fputs(const char*, FILE *); int fclose(file*); Swig가위의코드를 Wrapping하게되면자바에서는위함수들을아무문제없이사용할수있습니다. 아래는위함수를사용하는갂단한예제입니다. SWIGTYPE_p_FILE f = example.fopen( danguria, w ); Example.fputs( Hello danguria\n, f); Example.fclose(f); 다른언어들은 String 형태로저장되지만 C/C++ 포인터는자바에서 long 타입변수에저장됩니다. 다른스크립트언어들은컴파일러나인터프리터가 static type check 기능이없기때문에 swig runtime 에서제공하는 dynamic type checker 가사용됩니다. 하지만자바는자바클래스로
Wrapping되기때문에 type checking에대해서싞경쓰지않아도됩니다. 위의예제에서 FILE* 포인터는 SWIGTYPE_p_FILE이라는클래스로 Wrapping됩니다. 자바에서 type wrapper object가일단획득되면이오브젝트를매개변수로받는함수에인자로줄수있고, C/C++ 에서도자유롭게사용할수있습니다. 이런오브젝트에값을변경하는등의행위는자칫오동작을일으킬수있습니다. 형변홖이나기타자세한사항은 www.swig.org를통해확인하기바랍니다. 7. Structures C/C++ 의구조체는자바에서해당변수들에대한 setter, getter들이포함된클래스로 Wrapping됩니다. struct Vector{ double x, y, z; }; 위의코드와같은갂단한구조체는자바에서아래와같이사용될수있습니다. Vector v = new Vector(); v.setx(2.3); v.sety(3.5); double x = v.getx(); double y = v.gety(); A. %immutable 상수화된변수들은자동으로 setter함수가만들어지지않습니다. 하지만상수화되지않은변수를강제로 read-only 로만들기위해서해당변수위아래에 %immutable directive를쓰면됩니다. struct Danguria{ %immutable int x; char *name; %immutable }; // read-only members // read-only members A. Arrays 배열은 pointer와같은형식으로자바로 Wrapping됩니다. struct Danguria{ int x[16]; }; 위의구조체는자바에서다음과같은방식으로이용할수있습니다.
Danguria d = new Danguria(); SWIGTYPE_p_int x = d.getx(); Danguria e = new Danguria(); e.setx(x); 하지만위와같은사용은배열의범위체크를해주시않기때문에조심해서사용해야합니 다. 이를해결하기위한방안은 www.swig.org 의 Wrapping C Arrays with Java arrays 와 Unbound C Arrays 섹션을읽어보시기바랍니다. 8. C++ classes C/C++ 의클래스는구조체와마찬가지로자바의클래스로 Wrapping 됩니다. class List{ public: List(); ~List(); int search(char *item); void insert(char *item); char* get(int n); int length; }; 위와같은 C/C++ 코드는자바에서다음과같이사용될수있습니다. List list = new List(); l.insert( hi ); String item = l.get(0); int length = l.getlength();