swig 를 사용해서 파이썬 바인딩을 만들다보면
std::string 이나 std::wstring 을 뽑아내야 할 경우가 있습니다.

[code c++]
std::string GetFilePath()
{
return m_filePath;
}


공식적인 사용방법은 단지 std_string.i 를 include 해주면 됩니다.


%module 모듈네임

%include "std_string.i"

%{
%include "변환할헤더.h"
%}

%include "변환할헤더.h"


그런데...

리턴된 std::wstring 을 print 해보려고 하거나
[code c++]
std::wstring GetFilePathW()
{
return m_filePath;
}


print GetFilePathW() # 에러 발생


std::wstring 에 유니코드 값을 직접 넣으려고 하면
[code c++]
struct Data
{
std::wstring name;
};


data = Data()
data.name = u"haha" # 에러 발생

문제가 발생합니다.

이런 경우에는 다음처럼 typemap 을 구현해주면 잘 해결이 됩니다

%typemap(in) std::wstring {
if (PyUnicode_Check($input))
{
$1 = std::wstring((wchar_t*)PyUnicode_AS_DATA($input), PyUnicode_GetSize($input));
}
else
{
PyErr_SetString(PyExc_TypeError, "NOT_UNICODE");
return NULL;
}
}

%typemap(out) std::wstring {
$result = PyUnicode_FromWideChar($1.c_str(), $1.size());
}

슥슥 ~(-_-)~
이올린에 북마크하기(0) 이올린에 추천하기(0)
2009/02/11 18:56 2009/02/11 18:56
파이썬 바인딩을 위한 툴을 찾을때
boost::python 과 swig 를 놓고 고민하다가
swig 를 고르지 못한 이유는 메모릭 릭이 있다는 소문 때문이었습니다.

crtdbg 로 돌려보니 정말 메모리 릭이 있더군요 (-_-);

프로그램 실행도중 딱 한번만 할당 되는 부분이라
그다지 심각한 메모리릭은 아니지만 일단 찜찜해서 수정하는 코드를 만들어보았습니다.


SWIG_CLIENT_DATA_LEAK_CODE = """SWIGRUNTIME void
PySwigClientData_Del(PySwigClientData* data)
{
Py_XDECREF(data->newraw);
Py_XDECREF(data->newargs);
Py_XDECREF(data->destroy);
}"""


SWIG_CLIENT_DATA_SAFE_CODE = """SWIGRUNTIME void
PySwigClientData_Del(PySwigClientData* data)
{
Py_XDECREF(data->newraw);
Py_XDECREF(data->newargs);
Py_XDECREF(data->destroy);
free(data);
}"""

SWIG_GLOBALS_LEAK_CODE = """SWIGRUNTIME void
SWIG_Python_DestroyModule(void *vptr)
{
swig_module_info *swig_module = (swig_module_info *) vptr;
swig_type_info **types = swig_module->types;
size_t i;
for (i =0; i < swig_module->size; ++i) {
swig_type_info *ty = types[i];
if (ty->owndata) {
PySwigClientData *data = (PySwigClientData *) ty->clientdata;
if (data) PySwigClientData_Del(data);
}
}
Py_DECREF(SWIG_This());
}
"""

SWIG_GLOBALS_SAFE_CODE = """SWIGINTERN PyObject * SWIG_globals(void);
SWIGRUNTIME void
SWIG_Python_DestroyModule(void *vptr)
{
swig_module_info *swig_module = (swig_module_info *) vptr;
swig_type_info **types = swig_module->types;
size_t i;
for (i =0; i < swig_module->size; ++i) {
swig_type_info *ty = types[i];
if (ty->owndata) {
PySwigClientData *data = (PySwigClientData *) ty->clientdata;
if (data) PySwigClientData_Del(data);
}
}
Py_DECREF(SWIG_globals());
Py_DECREF(SWIG_This());
}
"""

def Fix(path):
print path
code = open(path).read()
code = code.replace(SWIG_CLIENT_DATA_LEAK_CODE, SWIG_CLIENT_DATA_SAFE_CODE)
code = code.replace(SWIG_GLOBALS_LEAK_CODE, SWIG_GLOBALS_SAFE_CODE)
open(path, "w").write(code)

if "__main__" == __name__:
import sys
if len(sys.argv) >= 2:
Fix(sys.argv[1])


swig.exe 실행후 나온 출력 파일을 인자로 코드를 수정해주는 스크립트입니다.
이올린에 북마크하기(0) 이올린에 추천하기(0)
2009/02/08 16:50 2009/02/08 16:50

python vc2005 에서 swig 사용하기

Posted at 2009/02/05 13:36// Posted in python/pyswig
SWIG 홈페이지
http://www.swig.org/

SWIG 다운로드
http://www.swig.org/download.html

The Latest Release

The latest development release is swig-1.3.38. View the release notes. Windows users should download swigwin-1.3.38 which includes a prebuilt executable.

파이썬 홈페이지
http://www.python.org/

파이썬 다운로드
http://www.python.org/download/

Download Standard Python Software

For the MD5 checksums and OpenPGP signatures, look at the detailed Python 2.6.1 page:



VC2005 준비 작업
- 테스트 프로젝트 생성
- swig.exe 와 lib 을 테스트 프로젝트로 복사


StdAfx.h 추가 내용
[code c++]
// PYTHON
#ifdef _DEBUG
# undef _DEBUG
# include <python.h>
# define _DEBUG
#else
# include <python.h>
#endif


main.cpp 예제 코드
[code c++]
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
Py_Initialize();

PyRun_SimpleString("print('haha')");

Py_Finalize();
return 0;
}


결과
haha
계속하려면 아무 키나 누르십시오 . . .

core.h 파일 추가
[code c++]
#pragma once

void info(const char* msg);


core.cpp 파일 추가
[code c++]
#include "stdafx.h"
#include "core.h"

void info(const char* msg)
{
puts(msg);
}


core.i 파일 추가

%module core

%{
#include "core.h"
%}

%include "core.h"


python_binding.h 파일 추가
[code c++]
#pragma once

void Py_LoadModules();


python_binding.cpp 파일 추가
[code c++]
#include "stdafx.h"

#pragma warning(disable:4996) // 문자열 함수 관련 경고 무시
#include "core_wrap.inc"

void Py_LoadModules()
{
init_core();
}


main.cpp 코드 수정
[code c++]
#include "stdafx.h"
#include "python_binding.h"

int _tmain(int argc, _TCHAR* argv[])
{
Py_Initialize();

Py_LoadModules();

PyRun_SimpleString("import core;core.info('ruru')");

Py_Finalize();
return 0;
}



사용자 지정 빌드 단계 구성
1. core.i 오른 클릭 -> 팝업 메뉴/속성 선택
2. core.i 속성 페이지 -> 사용자 지정 빌드 단계 선택
3. 내용 편집
- 명령줄: swig.exe -c++ -python -o $(InputName)_wrap.cpp $(InputPath)
- 설명: swig 인터페이스 파일 생성
- 출력: $(InputName)_wrap.cpp
- 추가 종속성: core.h


MSDN 참고자료:
http://msdn.microsoft.com/ko-kr/library/hefydhhy(VS.80).aspx
이올린에 북마크하기(0) 이올린에 추천하기(0)
2009/02/05 13:36 2009/02/05 13:36

python/와 ~(-_-)~ 좋다 swig

Posted at 2008/08/06 20:08// Posted in python/pyswig
boost::python 을 쓰게 된지도 1년 남짓이 되었습니다.
vc6 -> vc2005 로 바꾼 이후 컴파일 속도가 상대적(-_-)으로 빨라져서 쓰게되었습니다만...
이제 슬슬 인내력의 한계에 다다르게 되었습니다. 와아아아 =ㅁ=)/ 제길슨!

컴파일 속도도 답답하고
확장해서 쓰려고 해도 소스 코드도 개판이라 흑흑 ~(- -)~

그래서 며칠을 고민하던끝에 swig 나 한번 볼까 했는데!
엄청 편하군요 orz;

사용예 보기



헤더 파일만 정리 잘해서 연결만 시켜주면 끝이라는 사실이 너무 감동적입니다.
컴파일 속도도 빠른데다가
boost 에 비해서 읽을 수 있는 코드라는 점이 -_-)~
너무 너무 마음에 듭니다.

생성 코드 보기

shared_ptr 하고 weak_ptr 만 되면 boost::python 은 내다버려야겠어요.
이올린에 북마크하기(0) 이올린에 추천하기(0)
2008/08/06 20:08 2008/08/06 20:08
Tag , ,