SWIG에서 아름답게 작동하는 작은 프로젝트가 있습니다. 특히, 일부 함수는 std::vector
을 반환하는데, 이것은 파이썬의 튜플로 변환됩니다. 자, 나는 많은 수치를 처리하기 때문에, SWIG가 이들을 C++ 코드에서 반환 된 후에 numpy 배열로 변환합니다. 이를 위해 SWIG에서 다음과 같은 것을 사용합니다.SWIG의 새로운 내장 기능과 함께 pythonappend를 사용할 수있는 방법이 있습니까?
%feature("pythonappend") My::Cool::Namespace::Data() const %{ if isinstance(val, tuple) : val = numpy.array(val) %}
는 (사실, 난 val
실제로 튜플 있는지 확인 이유입니다, 수레를 돌려 일부 데이터라는 이름의 몇 가지 기능이 있습니다.) 이건 그냥 아름답게 작동합니다.
그러나 현재 사용할 수있는 -builtin
플래그도 사용하고 싶습니다. 이러한 데이터 함수에 대한 호출은 거의없고 대화식이기 때문에 느려짐이 문제는 아니지만 내장 옵션을 사용하여 속도가 크게 느린 다른 느린 루프가 있습니다.
문제는 그 플래그를 사용하면 pythonappend 기능이 자동으로 무시된다는 것입니다. 이제, 데이터는 튜플을 다시 반환합니다. 여전히 numpy 배열을 반환 할 수있는 방법이 있습니까? 나는 typemaps를 사용하여 시도했지만 거대한 엉망으로 바뀌었다.
편집 :
보레 올리 드는 질문에 매우 만족했습니다. 완전성을 위해 const 참조로 돌아 왔고 벡터 벡터 (시작하지 마라!)를 사용하기 때문에 필요한 몇 가지 미묘한 다른 typemaps를 포함합니다. 이것들은 다른 사람들이 사소한 차이점을 찾아 내려고 노력하는 것을 원하지 않기에 충분히 다릅니다.
%typemap(out) std::vector<int>& {
npy_intp result_size = $1->size();
npy_intp dims[1] = { result_size };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { dat[i] = (*$1)[i]; }
$result = PyArray_Return(npy_arr);
}
%typemap(out) std::vector<std::vector<int> >& {
npy_intp result_size = $1->size();
npy_intp result_size2 = (result_size>0 ? (*$1)[0].size() : 0);
npy_intp dims[2] = { result_size, result_size2 };
PyArrayObject* npy_arr = (PyArrayObject*)PyArray_SimpleNew(2, dims, NPY_INT);
int* dat = (int*) PyArray_DATA(npy_arr);
for (size_t i = 0; i < result_size; ++i) { for (size_t j = 0; j < result_size2; ++j) { dat[i*result_size2+j] = (*$1)[i][j]; } }
$result = PyArray_Return(npy_arr);
}
편집 2 :
나는 비슷한 문제가 스님의 접근 방식 (explained here) @ 사용하여 해결 될 수 찾고 있었다 꽤 무엇을 비록.
필자는 typemap을 작성하지 않고 C 측에서이 작업을 수행 할 수 없다고 생각합니다. -builtin이 pythonappend가 정상적으로 배치 된 코드를 제거하기 때문입니다. 빌더 인이 훨씬 빠릅니다 (즉 프로파일 링으로 사용하게 만들었습니까?) 저는 두 개의 모듈을 사용하고 하나는 -builtin을 사용하지 않으려 고합니다. – Flexo
'-builtin'이 pythonappend를 무시한다는 경고는 없습니다. numpy 배열에'std :: vector'를 typing하는 것에 대한 도전이 아닙니다. 나는 프로필을 작성했으며, 인터페이스에서 가장 귀찮은 루프를 상당히 빠르게 시작했습니다 (휴식을 취하기에는 너무 길지 않고 자주 기다리기에는 너무 길었습니다). 그러나 나는 또한이 루프를 내 C++ 코드로 옮길 수 있음을 깨달았다. 다소 어색하지만. 그래서 그것이 내가 갈 방법입니다. 그럼에도 불구하고 '두 모듈'제안은 흥미롭고 다른 경우 유용 할 수 있습니다. – Mike
SWIG를 -Wall과 통화 했습니까? 나는 그것이 그 경우에 경고 할 것이라고 생각했다. – Flexo