목차
원본 : http://www.swig.org/tutorial.html
시작하기#
짧은 시간내에 SWIG를 사용해보자. SWIG를 사용법을 설명하기 전에 변환하기를 원하는 C 파일을 가지고 있고 이것을 Tcl, Perl, Python, Java, C#에서 사용하고 싶다고 가정하자. 여기서 그 C 파일을example.c라고 하고, 내용은 아래와 같다.
#include <time.h>
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
char *get_time()
{
time_t ltime;
time(<ime);
return ctime(<ime);
}
Interface file#
위에서 본 C 파일을 당신이 원하는 언어에 추가하기 위해서 "interface file" 이라는 것을 만들어야 한다. 이러한 interface file은 아래와 같다.
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
Building a Tcl module#
UNIX에서는 다음과 같이 명령을 주면된다.(다른 운영체제는 SWIG Wiki Shared Libraries을 참고한다.)
unix % gcc -fpic -c example.c example_wrap.c \
-I/usr/local/include
unix % gcc -shared example.o example_wrap.o -o example.so
unix % tclsh
% load ./example.so example
% puts $My_variable
3.0
% fact 5
120
% my_mod 7 3
1
% get_time
Sun Feb 11 23:01:07 1996
%
SWIG 명령은 example_wrap.c라는 파일을 생성한다. 이 파일은 원본 소스파일과 같이 컴파일되어 공유 라이브러리 형태로 링크되어야 한다. Tcl의 경우는 Tcl에서 로드할 수 있는 동적 확장 모듈을 생성하였으며, load 명령으로 해당 모듈을 로드하여 사용하였다.
Building a Python module#
C 코드를 python 모듈로 변환하는 것도 쉽다. 간단히 아래의 예제를 따라하자.(다른 운영체제에서는 SWIG Wiki Shared Libraries 을 참고한다.)
unix % gcc -c example.c example_wrap.c \
-I/usr/local/include/python2.1
unix % ld -shared example.o example_wrap.o -o _example.so
이렇게 만들어진 python 모듈은 아래와 같이 사용할 수 있다.
>>> example.fact(5)
120
>>> example.my_mod(7,3)
1
>>> example.get_time()
'Sun Feb 11 23:01:07 1996'
>>>
Building a Perl module#
Perl5 모듈 또한 아래와 같이 쉽게 만들수 있다.
unix % gcc -c example.c example_wrap.c \
`perl -MExtUtils::Embed -e ccopts`
unix % ld -G example.o example_wrap.o -o example.so
unix % perl
use example;
print $example::My_variable,"\n";
print example::fact(5),"\n";
print example::get_time(),"\n";
<ctrl-d>
3.0
120
Sun Feb 11 23:01:07 1996
unix %
Building a Java module#
SWIG는 JAVA로부터 C/C++ 코드로의 접근을 위해 JNI 코드를 만들수 있다. JAVA 모듈을 만드는 예제는 아래와 같다.
$ gcc -c example.c example_wrap.c -I/c/jdk1.3.1/include -I/c/jdk1.3.1/include/win32
$ gcc -shared example.o example_wrap.o -mno-cygwin -Wl,--add-stdcall-alias -o example.dll
$ cat main.java
public class main {
public static void main(String argv[]) {
System.loadLibrary("example");
System.out.println(example.getMy_variable());
System.out.println(example.fact(5));
System.out.println(example.get_time());
}
}
$ javac main.java
$ java main
3.0
120
Mon Mar 4 18:20:31 2002
$
Building a C# module#
SWIG는 또한 C/C++의 코드를 C#에서 접근할 수 있도록 PInvoke를 사용하여 코드를 생성할 수 있다.
$ gcc -c -fpic example.c example_wrap.c
$ gcc -shared example.o example_wrap.o -o libexample.so
$ cscc -o runme *.cs
$ cat runme.cs
using System;
public class runme {
static void Main() {
Console.WriteLine(example.My_variable);
Console.WriteLine(example.fact(5));
Console.WriteLine(example.get_time());
}
}
$ ilrun runme
3
120
Tue May 13 10:45:45 2003
$
SWIG for the truly lazy#
interface file을 항상 꼭 작성해야 할 필요는 없다. 만약 header 파일을 가지고 있다면, SWIG interface 파일에서 직접적으로 header 파일을 포함할 수도 있다. 예를 들어,
%{
/* Includes the header in the wrapper code */
#include "header.h"
%}
/* Parse the header file to generate wrappers */
%include "header.h"
다른 방법으로는 header 파일에 조건 컴파일 문을 넣어 SWIG 지시문을 넣을 수도 있다. 예를 들어,
%module example
%{
#include "header.h"
%}
#endif
extern int fact(int n);
...
Running SWIG under Microsoft Windows#
SWIG는 32bit Windows 시리즈에서도 잘 동작한다.(95/98/NT/2000/XP) SWIG는 간단히 cmd 프롬프트에서 사용되어 지며, NMAKE와 같이 사용할 수 있다. 모듈들은 일반적으로 Tcl, Python 또는 어떤 언어든지 동적으로 로드될 수 있는 DLL 폼으로 컴파일된다. 약간의 노력을 더한다면, SWIG는 또한 MS Developer Studio상에서 사용자 빌드 옵션을 동해 사용될 수 있다.
That's it (well, more or less)#
시작하기 위해 알아야 할 체크리스트가 아래에 있다.
- 모듈 이름을 주어야한다.
- ANSI C/C++ 문법을 사용해야 한다.
- shared library module과 dynamic link library 컴파일 방법을 이해해야 한다.
- Relax...
Surely there's more to it...#
지금까지의 예제들은 의도적으로 간단하였지만, 일반적으로 보다 복잡한 C/C++ 프로그래밍 일을 요구한다. 사실, SWIG는 거의 모든 언어들의 특징을 지원하는 완벽한 C++ 컴파일러이다. SWIG는 preprocessing, pointers, classes, inheritance, 및 심지어 C++ templates 에 대한 지원을 포함한다. SWIG는 또한 대상 언어(target language)에서 structure와 class 들을 구조화하는데에도 사용된다.
이것을 설명하기 위해, 아래와 같은 C++ 자료 구조를 wrap하고 싶다고 하자.
namespace std {
template<class T1, class T2> struct pair {
T1 first;
T2 second;
pair() : first(T1()), second(T2()) { };
pair(const T1 &f, const T2 &s) : first(f), second(s) { }
};
}
SWIG로 래핑하기 위해서, 아래와 같은 interface를 만들자.
%module pair
%{
#include "pair.h"
%}
// Ignore the default constructor
%ignore std::pair::pair();
// Parse the original header file
%include "pair.h"
// Instantiate some templates
%template(pairii) std::pair<int,int>;
%template(pairdi) std::pair<double,int>;
이제 컴파일하자.(Python):
$ c++ -c pair_wrap.c -I/usr/local/include/python2.1
$ c++ -shared pair_wrap.o -o _pair.so
$ python
Python 2.1 (#3, Aug 20 2001, 15:41:42)
[GCC 2.95.2 19991024 (release)] on sunos5
Type "copyright", "credits" or "license" for more information.
>>> import pair
>>> a = pair.pairii(3,4)
>>> a.first
3
>>> a.second
4
>>> a.second = 16
>>> a.second
16
>>> b = pair.pairdi(3.5,8)
>>> b.first
3.5
>>> b.second
8
이 글은 스프링노트에서 작성되었습니다.